mirror of
https://github.com/aljazceru/njump.git
synced 2025-12-19 07:14:24 +01:00
mass tmpl migration: partials, other.html and archive.html.
This commit is contained in:
7
data.go
7
data.go
@@ -22,6 +22,7 @@ type Event struct {
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
templateId TemplateID
|
||||
typ string
|
||||
event *nostr.Event
|
||||
relays []string
|
||||
@@ -73,6 +74,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
authorRelays := []string{}
|
||||
var content string
|
||||
var typ string
|
||||
var templateId TemplateID
|
||||
|
||||
eventRelays := []string{}
|
||||
for _, relay := range relays {
|
||||
@@ -155,12 +157,10 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
}
|
||||
default:
|
||||
if event.Kind >= 30000 && event.Kind < 40000 {
|
||||
typ = "address"
|
||||
templateId = Other
|
||||
if d := event.Tags.GetFirst([]string{"d", ""}); d != nil {
|
||||
naddr, _ = nip19.EncodeEntity(event.PubKey, event.Kind, d.Value(), relaysForNip19)
|
||||
}
|
||||
} else {
|
||||
typ = "other"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
|
||||
}
|
||||
|
||||
return &Data{
|
||||
templateId: templateId,
|
||||
typ: typ,
|
||||
event: event,
|
||||
relays: eventRelays,
|
||||
|
||||
1
main.go
1
main.go
@@ -73,7 +73,6 @@ func main() {
|
||||
"profile": "profile.html",
|
||||
"profile_sitemap": "sitemap.xml",
|
||||
"note": "note.html",
|
||||
"address": "other.html",
|
||||
"relay": "relay.html",
|
||||
"relay_sitemap": "sitemap.xml",
|
||||
"archive": "archive.html",
|
||||
|
||||
119
pages.go
119
pages.go
@@ -10,6 +10,78 @@ import (
|
||||
"github.com/tylermmorton/tmpl"
|
||||
)
|
||||
|
||||
type TemplateID int
|
||||
|
||||
const (
|
||||
Profile TemplateID = iota
|
||||
Note
|
||||
LongForm
|
||||
TelegramInstantView
|
||||
Other
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed templates/head_common.html
|
||||
tmplHeadCommon string
|
||||
HeadCommonTemplate = tmpl.MustCompile(&HeadCommonPartial{})
|
||||
)
|
||||
|
||||
//tmpl:bind head_common.html
|
||||
type HeadCommonPartial struct {
|
||||
IsProfile bool
|
||||
}
|
||||
|
||||
func (*HeadCommonPartial) TemplateText() string {
|
||||
return tmplHeadCommon
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/top.html
|
||||
tmplTop string
|
||||
TopTemplate = tmpl.MustCompile(&TopPartial{})
|
||||
)
|
||||
|
||||
//tmpl:bind top.html
|
||||
type TopPartial struct{}
|
||||
|
||||
func (*TopPartial) TemplateText() string {
|
||||
return tmplTop
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/details.html
|
||||
tmplDetails string
|
||||
DetailsTemplate = tmpl.MustCompile(&DetailsPartial{})
|
||||
)
|
||||
|
||||
//tmpl:bind footer.html
|
||||
type DetailsPartial struct {
|
||||
HideDetails bool
|
||||
CreatedAt string
|
||||
EventJSON string
|
||||
Nevent string
|
||||
Kind int
|
||||
KindNIP string
|
||||
KindDescription string
|
||||
}
|
||||
|
||||
func (*DetailsPartial) TemplateText() string {
|
||||
return tmplDetails
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/footer.html
|
||||
tmplFooter string
|
||||
FooterTemplate = tmpl.MustCompile(&FooterPartial{})
|
||||
)
|
||||
|
||||
//tmpl:bind footer.html
|
||||
type FooterPartial struct{}
|
||||
|
||||
func (*FooterPartial) TemplateText() string {
|
||||
return tmplFooter
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/telegram_instant_view.html
|
||||
tmplTelegramInstantView string
|
||||
@@ -32,3 +104,50 @@ type TelegramInstantViewPage struct {
|
||||
func (*TelegramInstantViewPage) TemplateText() string {
|
||||
return tmplTelegramInstantView
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/archive.html
|
||||
tmplArchive string
|
||||
ArchiveTemplate = tmpl.MustCompile(&ArchivePage{})
|
||||
)
|
||||
|
||||
type ArchivePage struct {
|
||||
HeadCommonPartial `tmpl:"head_common"`
|
||||
TopPartial `tmpl:"top"`
|
||||
FooterPartial `tmpl:"footer"`
|
||||
|
||||
Title string
|
||||
PathPrefix string
|
||||
Data []string
|
||||
ModifiedAt string
|
||||
PaginationUrl string
|
||||
NextPage string
|
||||
PrevPage string
|
||||
}
|
||||
|
||||
func (*ArchivePage) TemplateText() string {
|
||||
return tmplArchive
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed templates/other.html
|
||||
tmplOther string
|
||||
OtherTemplate = tmpl.MustCompile(&OtherPage{})
|
||||
)
|
||||
|
||||
type OtherPage struct {
|
||||
HeadCommonPartial `tmpl:"head_common"`
|
||||
TopPartial `tmpl:"top"`
|
||||
DetailsPartial `tmpl:"details"`
|
||||
FooterPartial `tmpl:"footer"`
|
||||
|
||||
IsParameterizedReplaceable bool
|
||||
Naddr string
|
||||
Npub string
|
||||
Kind int
|
||||
KindDescription string
|
||||
}
|
||||
|
||||
func (*OtherPage) TemplateText() string {
|
||||
return tmplOther
|
||||
}
|
||||
|
||||
48
render.go
48
render.go
@@ -93,7 +93,7 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
(data.event.Kind == 1 && len(data.event.Content) > 650) || // or very long notes
|
||||
// or shorter notes that should be using text-to-image stuff but are not because they have video or images
|
||||
(data.event.Kind == 1 && len(data.event.Content) > 133 && !useTextImage) {
|
||||
data.typ = "telegram_instant_view"
|
||||
data.templateId = TelegramInstantView
|
||||
useTextImage = false
|
||||
}
|
||||
} else if style == "slack" || style == "discord" {
|
||||
@@ -231,6 +231,7 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Link", "<"+oembed+"&format=xml>; rel=\"alternate\"; type=\"text/xml+oembed\"")
|
||||
}
|
||||
|
||||
if currentTemplate, ok := templateMapping[data.typ]; ok {
|
||||
// template stuff
|
||||
params := map[string]any{
|
||||
"style": style,
|
||||
@@ -267,9 +268,16 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
"oembed": oembed,
|
||||
}
|
||||
|
||||
if err := tmpls.ExecuteTemplate(w, currentTemplate, params); err != nil {
|
||||
log.Error().Err(err).Msg("error rendering")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// migrating to templ
|
||||
if data.typ == "telegram_instant_view" {
|
||||
err := TelegramInstantViewTemplate.Render(w, &TelegramInstantViewPage{
|
||||
switch data.templateId {
|
||||
case TelegramInstantView:
|
||||
err = TelegramInstantViewTemplate.Render(w, &TelegramInstantViewPage{
|
||||
Video: data.video,
|
||||
VideoType: data.videoType,
|
||||
Image: data.image,
|
||||
@@ -281,22 +289,28 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
AuthorLong: data.authorLong,
|
||||
CreatedAt: data.createdAt,
|
||||
})
|
||||
case Other:
|
||||
err = OtherTemplate.Render(w, &OtherPage{
|
||||
HeadCommonPartial: HeadCommonPartial{IsProfile: false},
|
||||
DetailsPartial: DetailsPartial{
|
||||
HideDetails: false,
|
||||
CreatedAt: data.createdAt,
|
||||
KindDescription: data.kindDescription,
|
||||
KindNIP: data.kindNIP,
|
||||
EventJSON: string(eventJSON),
|
||||
Kind: data.event.Kind,
|
||||
},
|
||||
|
||||
IsParameterizedReplaceable: data.event.Kind >= 30000 && data.event.Kind < 40000,
|
||||
Naddr: data.naddr,
|
||||
Npub: data.npub,
|
||||
Kind: data.event.Kind,
|
||||
KindDescription: data.kindDescription,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error rendering tmpl")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// if a mapping is not found fallback to raw
|
||||
currentTemplate, ok := templateMapping[data.typ]
|
||||
if !ok {
|
||||
currentTemplate = "other.html"
|
||||
}
|
||||
|
||||
if err := tmpls.ExecuteTemplate(w, currentTemplate, params); err != nil {
|
||||
log.Error().Err(err).Msg("error rendering")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import (
|
||||
func renderArchive(w http.ResponseWriter, r *http.Request) {
|
||||
code := r.URL.Path[1:]
|
||||
hostname := code[2:]
|
||||
typ := "archive"
|
||||
resultsPerPage := 50
|
||||
isSitemap := false
|
||||
|
||||
if strings.HasSuffix(hostname, ".xml") {
|
||||
typ = "archive_sitemap"
|
||||
isSitemap = true
|
||||
resultsPerPage = 5000
|
||||
}
|
||||
|
||||
@@ -78,24 +78,25 @@ func renderArchive(w http.ResponseWriter, r *http.Request) {
|
||||
currentTime := time.Now()
|
||||
modifiedAt := currentTime.Add(-randomDuration).Format("2006-01-02T15:04:05Z07:00")
|
||||
|
||||
params := map[string]any{
|
||||
"title": title,
|
||||
"pathPrefix": path_prefix,
|
||||
"data": data,
|
||||
"modifiedAt": modifiedAt,
|
||||
"paginationUrl": area,
|
||||
"nextPage": fmt.Sprint(nextPage),
|
||||
"prevPage": fmt.Sprint(prevPage),
|
||||
}
|
||||
|
||||
if len(data) != 0 {
|
||||
w.Header().Set("Cache-Control", "max-age=3600")
|
||||
} else {
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
}
|
||||
|
||||
if err := tmpls.ExecuteTemplate(w, templateMapping[typ], params); err != nil {
|
||||
log.Error().Err(err).Msg("error rendering")
|
||||
return
|
||||
if !isSitemap {
|
||||
ArchiveTemplate.Render(w, &ArchivePage{
|
||||
HeadCommonPartial: HeadCommonPartial{IsProfile: false},
|
||||
|
||||
Title: title,
|
||||
PathPrefix: path_prefix,
|
||||
Data: data,
|
||||
ModifiedAt: modifiedAt,
|
||||
PaginationUrl: area,
|
||||
NextPage: fmt.Sprint(nextPage),
|
||||
PrevPage: fmt.Sprint(prevPage),
|
||||
})
|
||||
} else {
|
||||
// ArchiveSitemapTemplate.Render TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const type = '{{.type}}'
|
||||
let counts = []
|
||||
let clients = document.querySelectorAll('.client')
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
let name = clients[i].innerText
|
||||
let url = clients[i].href
|
||||
let key = 'nj:' + type + ':' + name
|
||||
let key = 'nj:' + name
|
||||
let count = parseInt(localStorage.getItem(key) || 0)
|
||||
clients[i].parentNode.setAttribute('count', count)
|
||||
clients[i].parentNode.setAttribute('title', 'Used ' + count + ' times')
|
||||
@@ -1,20 +1,20 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8" />
|
||||
<head>
|
||||
<title>{{.title}}</title>
|
||||
<title>{{.Title}}</title>
|
||||
|
||||
{{template "head_common.html" .}}
|
||||
{{template "head_common" .}}
|
||||
</head>
|
||||
|
||||
<body class="profile">
|
||||
{{template "top.html" .}}
|
||||
{{template "top" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
<div class="column columnA">
|
||||
<div class="info-wrapper">
|
||||
{{.title}}
|
||||
{{.Title}}
|
||||
<span class="display"> </span>
|
||||
</div>
|
||||
<div class="pic-wrapper"></div>
|
||||
@@ -22,31 +22,24 @@
|
||||
|
||||
<div class="column column_content">
|
||||
<div class="field info-wrapper">
|
||||
<h1 class="name">{{.title}}</h1>
|
||||
<h1 class="name">{{.Title}}</h1>
|
||||
</div>
|
||||
<div class="field separator long"></div>
|
||||
|
||||
<div class="field last_notes">
|
||||
{{range $element := .data }}
|
||||
<a
|
||||
href="/{{$.pathPrefix}}{{$element | trimProtocol | escapeString}}"
|
||||
class="note"
|
||||
>
|
||||
<div class="content">{{$element | escapeString}}</div>
|
||||
{{range $element := .Data }}
|
||||
<a href="/{{$.PathPrefix}}{{$element}}" class="note">
|
||||
<div class="content">{{$element}}</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if not (eq .prevPage "0")}}
|
||||
<a
|
||||
href="/{{.paginationUrl}}/{{.prevPage | escapeString}}"
|
||||
class="pagination prev"
|
||||
{{if not (eq .PrevPage "0")}}
|
||||
<a href="/{{.PaginationUrl}}/{{.PrevPage}}" class="pagination prev"
|
||||
><< Prev page</a
|
||||
>
|
||||
{{end}} {{if not (eq .nextPage "0")}}
|
||||
<a
|
||||
href="/{{.paginationUrl}}/{{.nextPage | escapeString}}"
|
||||
class="pagination next"
|
||||
{{end}} {{if not (eq .NextPage "0")}}
|
||||
<a href="/{{.PaginationUrl}}/{{.NextPage}}" class="pagination next"
|
||||
>Next page >></a
|
||||
>
|
||||
{{end}}
|
||||
@@ -56,10 +49,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
{{template "footer" .}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
<script src="/njump/static/scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,32 +1,23 @@
|
||||
<div
|
||||
class='field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}'
|
||||
>
|
||||
<div class="field {{if .HideDetails}}advanced{{end}}">
|
||||
<div class="label">Published at</div>
|
||||
{{.createdAt | escapeString}}
|
||||
{{.CreatedAt}}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class='field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}'
|
||||
>
|
||||
<div class="field {{if .HideDetails}}advanced{{end}}">
|
||||
<div class="label">Kind type</div>
|
||||
{{.event.Kind}} {{ if not (eq .kindNIP "")}} -
|
||||
<a
|
||||
href="https://github.com/nostr-protocol/nips/blob/master/{{.kindNIP | escapeString}}.md"
|
||||
>{{.kindDescription | escapeString}}</a
|
||||
{{.Kind}} {{ if not (eq .KindNIP "")}} -
|
||||
<a href="https://github.com/nostr-protocol/nips/blob/master/{{.KindNIP}}.md"
|
||||
>{{.KindDescription}}</a
|
||||
>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class='field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}}'
|
||||
>
|
||||
<div class="field {{if .HideDetails}}advanced{{end}}">
|
||||
<div class="label">Address Code</div>
|
||||
<div>{{.nevent}}</div>
|
||||
<div>{{.Nevent}}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class='field {{if not ( or (eq .type "other") (eq .type "address"))}}advanced{{end}} boxed'
|
||||
>
|
||||
<div class="field {{if .HideDetails}}advanced{{end}} boxed">
|
||||
<div class="label">Event JSON</div>
|
||||
<div class="json">{{.eventJSON}}</div>
|
||||
<div class="json">{{.EventJSON}}</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="/njump/static/styles.css?v=20230914" />
|
||||
|
||||
{{if eq .type "profile"}}
|
||||
{{if .IsProfile}}
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8" />
|
||||
<head>
|
||||
<title>njump - the nostr static gateway</title>
|
||||
<meta name="description" content="" />
|
||||
|
||||
{{template "head_common.html" .}}
|
||||
{{template "head_common" .}}
|
||||
</head>
|
||||
|
||||
<body class="homepage">
|
||||
{{template "top.html" .}}
|
||||
{{template "top" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
@@ -195,7 +195,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
{{template "footer" .}}
|
||||
|
||||
<script>
|
||||
// JavaScript object with a list of 50 names
|
||||
@@ -219,8 +219,6 @@
|
||||
// Add a click event listener to the link
|
||||
const pickRandomEntityLink = document.getElementById("pickRandomEntityLink");
|
||||
pickRandomEntityLink.addEventListener("click", pickRandomEntity);
|
||||
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8" />
|
||||
<head>
|
||||
{{ if eq .type "address" }}
|
||||
<title>Nostr Address {{.naddr | escapeString }}</title>
|
||||
{{end}} {{ if eq .type "other" }}
|
||||
<title>
|
||||
Nostr Event {{.kindID}} - {{.kindDescription | escapeString }}
|
||||
</title>
|
||||
{{end}} {{template "head_common.html" .}}
|
||||
{{ if .IsParameterizedReplaceable }}
|
||||
<title>Nostr Entity {{.Naddr}}</title>
|
||||
{{ else }}
|
||||
<title>Nostr Event {{.Kind}} - {{.KindDescription }}</title>
|
||||
{{ end }}
|
||||
|
||||
<!---->
|
||||
{{template "head_common" .}}
|
||||
</head>
|
||||
|
||||
<body class="other">
|
||||
{{template "top.html" .}}
|
||||
{{template "top" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
<div class="column column_content">
|
||||
<header class="profile_intro">
|
||||
<div class="info-wrapper">
|
||||
<div class="kind_desc">{{.kindDescription | escapeString}}</div>
|
||||
<div class="kind_desc">{{.KindDescription}}</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -27,20 +28,18 @@
|
||||
|
||||
<div class="field">
|
||||
<div class="label">Author Public key</div>
|
||||
<a href="/{{.npub | escapeString}}">{{.npub | escapeString}}</a>
|
||||
<a href="/{{.Npub}}">{{.Npub}}</a>
|
||||
</div>
|
||||
|
||||
{{template "details.html" .}}
|
||||
{{template "details" .DetailsPartial}}
|
||||
|
||||
<div class="field separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
{{template "footer" .}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
<script src="/njump/static/scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
{{if .npub}}
|
||||
<urlset xmlns="http://www.Sitemaps.Org/schemas/sitemap/0.9">
|
||||
{{if .Npub}}
|
||||
<url>
|
||||
<loc>https://{{s.CanonicalHost}}/{{.npub | escapeString}}</loc>
|
||||
<lastmod>{{.modifiedAt | escapeString}}</lastmod>
|
||||
<loc>https://{{s.CanonicalHost}}/{{.Npub | escapeString}}</loc>
|
||||
<lastmod>{{.ModifiedAt | escapeString}}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
{{end}}
|
||||
{{if .hostname}}
|
||||
{{if .Hostname}}
|
||||
<url>
|
||||
<loc>https://{{s.CanonicalHost}}/r/{{.hostname | escapeString}}</loc>
|
||||
<lastmod>{{.modifiedAt | escapeString}}</lastmod>
|
||||
<loc>https://{{s.CanonicalHost}}/r/{{.Hostname | escapeString}}</loc>
|
||||
<lastmod>{{.ModifiedAt | escapeString}}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
{{end}}
|
||||
{{if .lastNotes}}
|
||||
{{range .lastNotes}}
|
||||
{{if .LastNotes}}
|
||||
{{range .LastNotes}}
|
||||
<url>
|
||||
<loc>https://{{s.CanonicalHost}}/{{.Nevent | escapeString}}</loc>
|
||||
<lastmod>{{.ModifiedAt | escapeString}}</lastmod>
|
||||
@@ -26,11 +26,11 @@
|
||||
</url>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .data}}
|
||||
{{range $element := .data }}
|
||||
{{if .Data}}
|
||||
{{range $element := .Data }}
|
||||
<url>
|
||||
<loc>https://{{s.CanonicalHost}}/{{$.pathPrefix}}{{$element | trimProtocol | escapeString}}</loc>
|
||||
<lastmod>{{$.modifiedAt | escapeString}}</lastmod>
|
||||
<loc>https://{{s.CanonicalHost}}/{{$.PathPrefix}}{{$element | trimProtocol | escapeString}}</loc>
|
||||
<lastmod>{{$.ModifiedAt | escapeString}}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<header class="top">
|
||||
<a href="https://nostr.com" class="nostr_link">What is <span>nostr</span>?</a>
|
||||
<a href="https://nostr.com" class="nostr_link">What is <span>Nostr</span>?</a>
|
||||
<div class="theme-toggle">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
|
||||
Reference in New Issue
Block a user