mirror of
https://github.com/aljazceru/njump.git
synced 2026-02-12 01:24:28 +01:00
Merge pull request #1 from dtonon/feature/design-profile-note
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,5 @@
|
||||
njump
|
||||
.air.toml
|
||||
tmp/
|
||||
node_modules/
|
||||
.sass-cache/
|
||||
5
go.mod
5
go.mod
@@ -7,7 +7,7 @@ require (
|
||||
github.com/die-net/lrucache v0.0.0-20220628165024-20a71bc65bf1
|
||||
github.com/lukevers/freetype-go v0.0.0-20150513150840-77e276735410
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/nbd-wtf/go-nostr v0.18.1-0.20230509030905-52a493fd9666
|
||||
github.com/nbd-wtf/go-nostr v0.18.4
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b
|
||||
)
|
||||
@@ -23,6 +23,9 @@ require (
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
)
|
||||
|
||||
14
go.sum
14
go.sum
@@ -69,8 +69,12 @@ github.com/lukevers/freetype-go v0.0.0-20150513150840-77e276735410 h1:ED5jVfC//X
|
||||
github.com/lukevers/freetype-go v0.0.0-20150513150840-77e276735410/go.mod h1:cnsFc3HOpydgckvXF3xq4fvlLFOAuTh4VyJ118x8LQc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/nbd-wtf/go-nostr v0.18.1-0.20230509030905-52a493fd9666 h1:dWnwxgOl+dnVsKQLoNo5TaYJB7opG3LUIZ0YPl63iQI=
|
||||
github.com/nbd-wtf/go-nostr v0.18.1-0.20230509030905-52a493fd9666/go.mod h1:fN8trCzHEtsf2954h8neqNERM/OXnCYI71nA4wWCobI=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4-0.20230514132335-123d3a6a9ab1 h1:rfkAcjBBR7j9aHRYIn+VjCO12lt8Bero5/cYPmO6Q6Q=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4-0.20230514132335-123d3a6a9ab1/go.mod h1:GPJOOK8US38kz+bfb9nWe873Xu0e6bXlThejOs1LTkc=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4-0.20230525112312-5c0f8bff83ea h1:L4eHtPd5bgj7Cl9j+TA5fZaQGVPt8SunZhqNtMbqzWo=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4-0.20230525112312-5c0f8bff83ea/go.mod h1:GPJOOK8US38kz+bfb9nWe873Xu0e6bXlThejOs1LTkc=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4 h1:P5qHEvvwS6DMaDMD82fP66M3kFBJnNQATczGH93rC0s=
|
||||
github.com/nbd-wtf/go-nostr v0.18.4/go.mod h1:GPJOOK8US38kz+bfb9nWe873Xu0e6bXlThejOs1LTkc=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@@ -92,6 +96,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q=
|
||||
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
||||
4
justfile
4
justfile
@@ -6,3 +6,7 @@ deploy: build
|
||||
rsync njump turgot:njump/njump-new
|
||||
ssh turgot 'mv njump/njump-new njump/njump'
|
||||
ssh root@turgot 'systemctl start njump'
|
||||
|
||||
refresh_build:
|
||||
sass static/styles.scss static/styles.css
|
||||
go build -o ./tmp/main .
|
||||
3
main.go
3
main.go
@@ -7,6 +7,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
|
||||
http.HandleFunc("/image/", generate)
|
||||
http.HandleFunc("/proxy/", proxy)
|
||||
http.HandleFunc("/", render)
|
||||
|
||||
212
package-lock.json
generated
Normal file
212
package-lock.json
generated
Normal file
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"name": "njump",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"sass": "^1.62.1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
||||
"integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.62.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",
|
||||
"integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==",
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
package.json
Normal file
5
package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"sass": "^1.62.1"
|
||||
}
|
||||
}
|
||||
40
render.go
40
render.go
@@ -4,19 +4,24 @@ import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"time"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
//go:embed event.html
|
||||
var eventHTML string
|
||||
//go:embed static/raw.html
|
||||
var rawHTML string
|
||||
|
||||
var tmpl = template.Must(template.New("event").Parse(eventHTML))
|
||||
//go:embed static/profile.html
|
||||
var profileHTML string
|
||||
|
||||
//go:embed static/note.html
|
||||
var noteHTML string
|
||||
|
||||
func render(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println(r.URL.Path, ":~", r.Header.Get("user-agent"))
|
||||
@@ -48,10 +53,11 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
npub, _ := nip19.EncodePublicKey(event.PubKey)
|
||||
nevent, _ := nip19.EncodeEvent(event.ID, []string{}, event.PubKey)
|
||||
naddr := ""
|
||||
createdAt := time.Unix(int64(event.CreatedAt), 0).Format("2006-01-02 15:04:05")
|
||||
|
||||
author := event
|
||||
if event.Kind != 0 {
|
||||
typ = "event"
|
||||
typ = "note"
|
||||
author, _ = getEvent(r.Context(), npub)
|
||||
|
||||
if event.Kind >= 30000 && event.Kind < 40000 {
|
||||
@@ -154,19 +160,24 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
description = prettyJsonOrRaw(event.Content)
|
||||
}
|
||||
|
||||
content := prettyJsonOrRaw(event.Content)
|
||||
|
||||
eventJSON, _ := json.MarshalIndent(event, "", " ")
|
||||
|
||||
params := map[string]any{
|
||||
"createdAt": createdAt,
|
||||
"clients": generateClientList(code, event),
|
||||
"type": typ,
|
||||
"title": title,
|
||||
"twitterTitle": twitterTitle,
|
||||
"npub": npub,
|
||||
"npubShort": npubShort,
|
||||
"nevent": nevent,
|
||||
"naddr": naddr,
|
||||
"metadata": metadata,
|
||||
"authorLong": authorLong,
|
||||
"description": description,
|
||||
"content": content,
|
||||
"textImageURL": textImageURL,
|
||||
"videoType": videoType,
|
||||
"image": image,
|
||||
@@ -174,6 +185,25 @@ func render(w http.ResponseWriter, r *http.Request) {
|
||||
"proxy": "https://" + hostname + "/proxy?src=",
|
||||
"eventJSON": string(eventJSON),
|
||||
}
|
||||
|
||||
templates := make(map[string]string)
|
||||
templates["profile"] = profileHTML
|
||||
templates["note"] = noteHTML
|
||||
templates["address"] = rawHTML
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"BasicFormatting": BasicFormatting,
|
||||
"SanitizeString": html.EscapeString,
|
||||
}
|
||||
|
||||
tmpl, err := template.Must(template.New("event").
|
||||
Funcs(funcMap).
|
||||
Parse(templates[typ])).
|
||||
ParseFiles("static/head.html", "static/top.html", "static/column_clients.html", "static/footer.html", "static/scripts.js")
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
if err := tmpl.ExecuteTemplate(w, "event", params); err != nil {
|
||||
http.Error(w, "error rendering: "+err.Error(), 500)
|
||||
return
|
||||
|
||||
22
static/column_clients.html
Normal file
22
static/column_clients.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="column column_clients">
|
||||
<div class="title open-list">
|
||||
<span class="text">Open {{.type}} in</span>
|
||||
<span class="open">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill="#FAFAFA" fill-rule="evenodd" d="M3.808.355h2.85a2.85 2.85 0 0 1 2.85 2.85v2.85a2.85 2.85 0 0 1-2.85 2.85h-2.85a2.85 2.85 0 0 1-2.85-2.85v-2.85a2.85 2.85 0 0 1 2.85-2.85Zm2.85 6.65a.95.95 0 0 0 .95-.95v-2.85a.95.95 0 0 0-.95-.95h-2.85a.95.95 0 0 0-.95.95v2.85c0 .525.425.95.95.95h2.85Zm0 3.8h-2.85a2.85 2.85 0 0 0-2.85 2.85v2.85a2.85 2.85 0 0 0 2.85 2.85h2.85a2.85 2.85 0 0 0 2.85-2.85v-2.85a2.85 2.85 0 0 0-2.85-2.85Zm0 6.65a.95.95 0 0 0 .95-.95v-2.85a.95.95 0 0 0-.95-.95h-2.85a.95.95 0 0 0-.95.95v2.85c0 .525.425.95.95.95h2.85Zm10.45-6.65h-2.85a2.85 2.85 0 0 0-2.85 2.85v2.85a2.85 2.85 0 0 0 2.85 2.85h2.85a2.85 2.85 0 0 0 2.85-2.85v-2.85a2.85 2.85 0 0 0-2.85-2.85Zm0 6.65a.95.95 0 0 0 .95-.95v-2.85a.95.95 0 0 0-.95-.95h-2.85a.95.95 0 0 0-.95.95v2.85c0 .525.425.95.95.95h2.85Zm0-17.1h-2.85a2.85 2.85 0 0 0-2.85 2.85v2.85a2.85 2.85 0 0 0 2.85 2.85h2.85a2.85 2.85 0 0 0 2.85-2.85v-2.85a2.85 2.85 0 0 0-2.85-2.85Zm0 6.65a.95.95 0 0 0 .95-.95v-2.85a.95.95 0 0 0-.95-.95h-2.85a.95.95 0 0 0-.95.95v2.85c0 .525.425.95.95.95h2.85Z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="close">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="31" height="16" fill="currentColor" viewBox="0 0 31 16">
|
||||
<path fill="#fff" d="M30.207 3.016 16.744 14.983a1.496 1.496 0 0 1-1.974 0L1.307 3.016A1.496 1.496 0 0 1 3.28.772l12.476 11.085L28.233.772a1.496 1.496 0 1 1 1.974 2.244Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clients_wrapper">
|
||||
{{range .clients}}
|
||||
<div class="btn">
|
||||
<a class="client" href="{{.url}}"><span>Open {{.type}} in</span> {{.name}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
16
static/footer.html
Normal file
16
static/footer.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="background"></div>
|
||||
|
||||
<div class="footer">
|
||||
Powered by <a href="https://git.fiatjaf.com/njump">njump</a>
|
||||
</div>
|
||||
|
||||
<svg width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<clipPath id="svg-shape" clipPathUnits="objectBoundingBox">
|
||||
<path
|
||||
transform="scale(0.005, 0.005)"
|
||||
d="M100,200c43.8,0,68.2,0,84.1-15.9C200,168.2,200,143.8,200,100s0-68.2-15.9-84.1C168.2,0,143.8,0,100,0S31.8,0,15.9,15.9C0,31.8,0,56.2,0,100s0,68.2,15.9,84.1C31.8,200,56.2,200,100,200z"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
51
static/head.html
Normal file
51
static/head.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<head>
|
||||
{{if eq .type "profile"}}
|
||||
<title>Nostr Public Key {{.npub}}</title>
|
||||
<meta property="og:site_name" content="{{.npub | SanitizeString}}" />
|
||||
<meta property="og:title" content="{{.title | SanitizeString}}" />
|
||||
{{ if .metadata.Picture }}
|
||||
<meta property="og:image" content="{{.metadata.Picture | SanitizeString}}" />
|
||||
<meta property="twitter:image" content="{{.proxy}}{{.metadata.Picture | SanitizeString}}" />
|
||||
{{end}} {{ if .metadata.About }}
|
||||
<meta property="og:description" content="{{.metadata.About | SanitizeString}}" />
|
||||
{{end}}
|
||||
<meta property="twitter:card" content="summary" />
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "event" }}
|
||||
<title>Nostr Event {{.nevent}}</title>
|
||||
<meta property="og:site_name" content="{{.authorLong | SanitizeString}}" />
|
||||
<meta property="og:title" content="{{.title | SanitizeString}}" />
|
||||
<meta name="twitter:title" content="{{.twitterTitle | SanitizeString}}" />
|
||||
<!---->
|
||||
{{ if .textImageURL }}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@nostrprotocol" />
|
||||
<meta property="og:image" content="{{.textImageURL | SanitizeString}}" />
|
||||
<meta name="twitter:image" content="{{.textImageURL | SanitizeString}}" />
|
||||
{{ else }}
|
||||
<!---->
|
||||
<meta property="twitter:card" content="summary" />
|
||||
{{ if .image }}
|
||||
<meta property="og:image" content="{{.image | SanitizeString}}" />
|
||||
<meta name="twitter:image" content="{{.proxy}}{{.image | SanitizeString}}" />
|
||||
{{end}} {{ if .video }}
|
||||
<meta property="og:video" content="{{.video | SanitizeString}}" />
|
||||
<meta property="og:video:secure_url" content="{{.video | SanitizeString}}" />
|
||||
<meta property="og:video:type" content="video/{{.videoType | SanitizeString}}" />
|
||||
{{end}}
|
||||
<!---->
|
||||
{{end}}
|
||||
<meta property="og:description" content="{{.description | SanitizeString}}" />
|
||||
<meta name="twitter:description" content="{{.description | SanitizeString}}" />
|
||||
{{end}}
|
||||
<!----------->
|
||||
{{ if eq .type "address" }}
|
||||
<title>Nostr Address {{.naddr | SanitizeString }}</title>
|
||||
{{end}}
|
||||
<!----------->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/static/styles.css?v=20230527" />
|
||||
|
||||
</head>
|
||||
81
static/note.html
Normal file
81
static/note.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8">
|
||||
{{template "head.html" .}}
|
||||
|
||||
<body class="note">
|
||||
|
||||
{{template "top.html" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
|
||||
<div class="column column_content">
|
||||
|
||||
<div class="profile_intro">
|
||||
<a href="/{{.npub | SanitizeString}}">
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.metadata.Picture | SanitizeString}}" />
|
||||
</div>
|
||||
<div class="info-wrapper">
|
||||
<div class="name">
|
||||
{{.metadata.Name | SanitizeString}} <span class="display">{{.metadata.DisplayName | SanitizeString}}</span>
|
||||
</div>
|
||||
<div class="npub">{{.npubShort | SanitizeString}}</div>
|
||||
</div>
|
||||
<div class="published_at">
|
||||
{{.createdAt | SanitizeString}}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="field separator"></div>
|
||||
|
||||
<div class="field content">
|
||||
{{.content | SanitizeString | BasicFormatting }}
|
||||
</div>
|
||||
|
||||
<div class="field separator"></div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label">Author Public key</div>
|
||||
{{.npub}}
|
||||
</div>
|
||||
|
||||
<div class="field last_update">
|
||||
Last update:<br/>
|
||||
{{.createdAt | SanitizeString}}
|
||||
</div>
|
||||
|
||||
<div class="field advanced-switch-wrapper">
|
||||
<input type="checkbox" id="advanced-switch" class="advanced-switch" />
|
||||
<label for="advanced-switch">X</label>
|
||||
<label for="advanced-switch">Show more details</label>
|
||||
</div>
|
||||
|
||||
<div class="field advanced">
|
||||
<div class="label">Nevent</div>
|
||||
<div>{{.nevent | SanitizeString}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field advanced boxed">
|
||||
<div class="label">Event JSON</div>
|
||||
<div class="json">{{.eventJSON | SanitizeString}}</div>
|
||||
</div>
|
||||
<div class="field separator"></div>
|
||||
</div>
|
||||
|
||||
{{template "column_clients.html" .}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
89
static/profile.html
Normal file
89
static/profile.html
Normal file
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default">
|
||||
<meta charset="UTF-8">
|
||||
{{template "head.html" .}}
|
||||
|
||||
<body class="profile">
|
||||
|
||||
{{template "top.html" .}}
|
||||
|
||||
<div class="container_wrapper">
|
||||
<div class="container">
|
||||
|
||||
<div class="column columnA">
|
||||
<div class="info-wrapper">
|
||||
{{.metadata.Name | SanitizeString}} <span class="display">{{.metadata.DisplayName | SanitizeString}}</span>
|
||||
</div>
|
||||
<div class="pic-wrapper">
|
||||
<img class="pic" src="{{.metadata.Picture | SanitizeString}}" />
|
||||
</div>
|
||||
<div class="last_update">
|
||||
Last update:<br/>
|
||||
{{.createdAt | SanitizeString}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column column_content">
|
||||
<div class="field info-wrapper">
|
||||
<div class="name">
|
||||
{{.metadata.Name | SanitizeString}} <span class="display">{{.metadata.DisplayName | SanitizeString}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field separator long"></div>
|
||||
<div class="field">
|
||||
<a href="{{.metadata.Website | SanitizeString}}">{{.metadata.Website | SanitizeString}}</a>
|
||||
</div>
|
||||
<div class="field">
|
||||
{{.metadata.About | SanitizeString}}
|
||||
</div>
|
||||
<div class="field separator"></div>
|
||||
<div class="field">
|
||||
<div class="label">Public key</div>
|
||||
{{.npub | SanitizeString}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">NIP-05</div>
|
||||
{{.metadata.NIP05 | SanitizeString}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">LN Address</div>
|
||||
{{.metadata.LUD16 | SanitizeString}}
|
||||
</div>
|
||||
|
||||
<div class="field last_update">
|
||||
Last update:<br/>
|
||||
{{.createdAt | SanitizeString}}
|
||||
</div>
|
||||
|
||||
<div class="field advanced-switch-wrapper">
|
||||
<input type="checkbox" id="advanced-switch" class="advanced-switch" />
|
||||
<label for="advanced-switch">X</label>
|
||||
<label for="advanced-switch">Show more details</label>
|
||||
</div>
|
||||
|
||||
<div class="field advanced">
|
||||
<div class="label">Metadata Event</div>
|
||||
<div>{{.nevent | SanitizeString}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field advanced boxed">
|
||||
<div class="label">Event JSON</div>
|
||||
<div class="json">{{.eventJSON}}</div>
|
||||
</div>
|
||||
<div class="field separator"></div>
|
||||
</div>
|
||||
|
||||
{{template "column_clients.html" .}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
|
||||
<script>
|
||||
{{template "scripts.js"}}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
97
static/scripts.js
Normal file
97
static/scripts.js
Normal file
@@ -0,0 +1,97 @@
|
||||
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 count = parseInt(localStorage.getItem(key) || 0)
|
||||
clients[i].parentNode.setAttribute('count', count)
|
||||
clients[i].parentNode.setAttribute('title', 'Used ' + count + ' times')
|
||||
clients[i].addEventListener('click', () => {
|
||||
localStorage.setItem(key, count + 1)
|
||||
})
|
||||
counts.push([count, name, url])
|
||||
}
|
||||
|
||||
// Reorder clients following the counter
|
||||
let clients_wrapper = document.querySelector('.clients_wrapper')
|
||||
const elements = Array.from(clients_wrapper.getElementsByClassName('btn'))
|
||||
elements.sort((a, b) => {
|
||||
const rankA = parseInt(a.getAttribute('count'))
|
||||
const rankB = parseInt(b.getAttribute('count'))
|
||||
return rankB - rankA
|
||||
})
|
||||
elements.forEach(element => clients_wrapper.appendChild(element))
|
||||
|
||||
counts.sort((a, b) => b[0] - a[0])
|
||||
let tailsum = counts.slice(1).reduce((acc, c) => acc + c[0], 0)
|
||||
|
||||
if (location.hash !== '#noredirect') {
|
||||
if (counts[0][0] - tailsum > 10) {
|
||||
location.href = counts[0][2]
|
||||
}
|
||||
}
|
||||
|
||||
let jsons = document.querySelectorAll('.json')
|
||||
for (let i = 0; i < jsons.length; i++) {
|
||||
console.log(jsons[i].innerHTML)
|
||||
jsons[i].innerHTML = syntaxHighlight(jsons[i].innerHTML)
|
||||
}
|
||||
|
||||
const shareButton = document.querySelector('.open-list')
|
||||
const clients_list = document.querySelector('.column_clients')
|
||||
shareButton.addEventListener('click', function () {
|
||||
clients_list.classList.toggle('up')
|
||||
if (clients_list.classList.contains('up')) {
|
||||
document.body.classList.add('lock')
|
||||
} else {
|
||||
document.body.classList.remove('lock')
|
||||
}
|
||||
})
|
||||
|
||||
function updateAdvanceSwitch() {
|
||||
advanced_list.forEach(element => {
|
||||
if (advanceSwitch.checked) {
|
||||
element.classList.add('visible')
|
||||
} else {
|
||||
element.classList.remove('visible')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const advanceSwitch = document.querySelector('.advanced-switch')
|
||||
const advanced_list = document.querySelectorAll('.advanced')
|
||||
advanceSwitch.addEventListener('change', function () {
|
||||
updateAdvanceSwitch()
|
||||
})
|
||||
|
||||
updateAdvanceSwitch() // Check at the page load, some browsers keep the state in cache
|
||||
|
||||
var url = new URL(window.location.href)
|
||||
var searchParams = new URLSearchParams(url.search)
|
||||
if (searchParams.has('details') && searchParams.get('details') == 'yes') {
|
||||
advanceSwitch.click()
|
||||
}
|
||||
|
||||
function syntaxHighlight(json) {
|
||||
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
return json.replace(
|
||||
/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
|
||||
function (match) {
|
||||
var cls = 'number'
|
||||
if (/^"/.test(match)) {
|
||||
if (/:$/.test(match)) {
|
||||
cls = 'key'
|
||||
} else {
|
||||
cls = 'string'
|
||||
}
|
||||
} else if (/true|false/.test(match)) {
|
||||
cls = 'boolean'
|
||||
} else if (/null/.test(match)) {
|
||||
cls = 'null'
|
||||
}
|
||||
return '<span class="' + cls + '">' + match + '</span>'
|
||||
}
|
||||
)
|
||||
}
|
||||
657
static/styles.css
Normal file
657
static/styles.css
Normal file
@@ -0,0 +1,657 @@
|
||||
|
||||
html {
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 19px;
|
||||
font-weight: 300;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
html {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
.theme--default body {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark body {
|
||||
color: #FAFAFA;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.lock {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.theme--default a {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark a {
|
||||
color: #FAFAFA;
|
||||
}
|
||||
|
||||
.background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
.theme--default .background {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
.theme--dark .background {
|
||||
background: #1e1e1e;
|
||||
}
|
||||
.background::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 140%;
|
||||
height: 100%;
|
||||
transform: rotate(-20deg);
|
||||
transform-origin: bottom;
|
||||
bottom: -40%;
|
||||
}
|
||||
.theme--default .background::after {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
.theme--dark .background::after {
|
||||
background: #181818;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.background::after {
|
||||
width: 200%;
|
||||
bottom: -40%;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
.theme--default .theme-toggle {
|
||||
color: #F3F3F3;
|
||||
}
|
||||
.theme--dark .theme-toggle {
|
||||
color: #9a9a9a;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.theme-toggle {
|
||||
position: relative;
|
||||
float: right;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sun {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.moon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.theme--dark .sun {
|
||||
display: block;
|
||||
}
|
||||
.theme--dark .moon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 1rem 0;
|
||||
justify-content: left;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.top {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 1rem auto 1rem auto;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
.theme--default .top span {
|
||||
color: #E32A6D;
|
||||
}
|
||||
.theme--dark .top span {
|
||||
color: #E32A6D;
|
||||
}
|
||||
|
||||
.pic-wrapper {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.pic-wrapper {
|
||||
flex-basis: 40%;
|
||||
}
|
||||
}
|
||||
.pic-wrapper img.pic {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
-webkit-clip-path: url(#svg-shape);
|
||||
-moz-clip-path: url(#svg-shape);
|
||||
-o-clip-path: url(#svg-shape);
|
||||
-ms-clip-path: url(#svg-shape);
|
||||
clip-path: url(#svg-shape);
|
||||
}
|
||||
|
||||
.container_wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container_wrapper {
|
||||
display: block;
|
||||
padding: 0 1rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.nostr_link {
|
||||
flex-basis: 15%;
|
||||
text-align: right;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
width: 70%;
|
||||
justify-content: space-between;
|
||||
gap: 4.8vw;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.container .columnA {
|
||||
flex-basis: 25%;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .columnA {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0rem;
|
||||
}
|
||||
}
|
||||
.container .columnA .info-wrapper {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .columnA .info-wrapper {
|
||||
display: block;
|
||||
flex-basis: 64%;
|
||||
max-width: 64%;
|
||||
overflow: hidden;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.container .columnA .info-wrapper .display {
|
||||
display: block;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.theme--default .container .columnA .info-wrapper .display {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .columnA .info-wrapper .display {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
}
|
||||
.container .columnA .last_update {
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
.theme--default .container .columnA .last_update {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .columnA .last_update {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .columnA .last_update {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.container .column_content {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
word-wrap: break-word;
|
||||
margin-right: 1vw;
|
||||
}
|
||||
.container .column_content .info-wrapper {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.theme--default .container .column_content .info-wrapper .display {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .column_content .info-wrapper .display {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.container .column_content .info-wrapper .npub {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.theme--default .container .column_content .info-wrapper .npub {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .column_content .info-wrapper .npub {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_content .info-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.container .column_content .separator {
|
||||
height: 6px;
|
||||
width: 30%;
|
||||
margin-left: -0.6rem;
|
||||
}
|
||||
.theme--default .container .column_content .separator {
|
||||
background: #F3F3F3;
|
||||
}
|
||||
.theme--dark .container .column_content .separator {
|
||||
background: #232323;
|
||||
}
|
||||
.container .column_content .separator.long {
|
||||
width: 50%;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_content .separator {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
}
|
||||
.container .column_content .field {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.container .column_content .field .label {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.theme--default .container .column_content .field .label {
|
||||
color: #E32A6D;
|
||||
}
|
||||
.theme--dark .container .column_content .field .label {
|
||||
color: #E32A6D;
|
||||
}
|
||||
.container .column_content .field.advanced {
|
||||
display: none;
|
||||
}
|
||||
.container .column_content .field.advanced.visible {
|
||||
display: block;
|
||||
}
|
||||
.container .column_content .field.advanced.boxed {
|
||||
padding: 0 1rem 1rem;
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
}
|
||||
.theme--default .container .column_content .field.advanced.boxed {
|
||||
background: #F3F3F3;
|
||||
}
|
||||
.theme--dark .container .column_content .field.advanced.boxed {
|
||||
background: #131313;
|
||||
}
|
||||
.container .column_content .field.advanced.boxed .label {
|
||||
padding: 0.2rem 1rem;
|
||||
margin: 0 -1rem;
|
||||
}
|
||||
.theme--default .container .column_content .field.advanced.boxed .label {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark .container .column_content .field.advanced.boxed .label {
|
||||
color: #9a9a9a;
|
||||
}
|
||||
.theme--default .container .column_content .field.advanced.boxed .label {
|
||||
background: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .column_content .field.advanced.boxed .label {
|
||||
background: #191919;
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper input[type=checkbox] {
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper label:first-of-type {
|
||||
cursor: pointer;
|
||||
text-indent: -9999px;
|
||||
width: 2.6rem;
|
||||
height: 1.2rem;
|
||||
background: #3d3d3d;
|
||||
display: inline-block;
|
||||
border-radius: 100px;
|
||||
position: relative;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_content .field.advanced-switch-wrapper label:first-of-type {
|
||||
width: 3rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper label:first-of-type:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background: #fff;
|
||||
border-radius: 1rem;
|
||||
transition: 0.2s;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_content .field.advanced-switch-wrapper label:first-of-type:after {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
}
|
||||
.theme--default .container .column_content .field.advanced-switch-wrapper input:checked + label {
|
||||
background: #E32A6D;
|
||||
}
|
||||
.theme--dark .container .column_content .field.advanced-switch-wrapper input:checked + label {
|
||||
background: #E32A6D;
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper input:checked + label:first-of-type:after {
|
||||
left: calc(100% - 2px);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.container .column_content .field.advanced-switch-wrapper label:first-of-type:active:after {
|
||||
width: 2rem;
|
||||
}
|
||||
.container .column_content .field.content {
|
||||
line-height: 1.4rem;
|
||||
}
|
||||
.container .column_content .field.content img {
|
||||
max-width: 100%;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.container .column_content .field .json, .container .column_content .field .data {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.container .column_content .field .json .key, .container .column_content .field .data .key {
|
||||
display: inline-block;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.theme--default .container .column_content .field .json .key, .theme--default .container .column_content .field .data .key {
|
||||
color: #E32A6D;
|
||||
}
|
||||
.theme--dark .container .column_content .field .json .key, .theme--dark .container .column_content .field .data .key {
|
||||
color: #E32A6D;
|
||||
}
|
||||
.theme--default .container .column_content .field .json .string, .theme--default .container .column_content .field .data .string {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark .container .column_content .field .json .string, .theme--dark .container .column_content .field .data .string {
|
||||
color: #FAFAFA;
|
||||
}
|
||||
.container .column_content .field .json .number, .container .column_content .field .data .number {
|
||||
color: darkorange;
|
||||
}
|
||||
.theme--default .container .column_content .field .json .boolean, .theme--default .container .column_content .field .data .boolean {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark .container .column_content .field .json .boolean, .theme--dark .container .column_content .field .data .boolean {
|
||||
color: #FAFAFA;
|
||||
}
|
||||
.theme--default .container .column_content .field .json .null, .theme--default .container .column_content .field .data .null {
|
||||
color: #373737;
|
||||
}
|
||||
.theme--dark .container .column_content .field .json .null, .theme--dark .container .column_content .field .data .null {
|
||||
color: #FAFAFA;
|
||||
}
|
||||
.container .column_content .field.last_update {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_content .field.last_update {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.theme--default .container .column_content .field.last_update {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
.theme--dark .container .column_content .field.last_update {
|
||||
color: #C9C9C9;
|
||||
}
|
||||
}
|
||||
.container .column_clients {
|
||||
flex-basis: 25%;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: all 500ms ease-in-out;
|
||||
}
|
||||
.container .column_clients.up .btn {
|
||||
display: block;
|
||||
}
|
||||
.container .column_clients.up .title span.open {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.container .column_clients .title {
|
||||
font-size: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.container .column_clients .title span.open, .container .column_clients .title span.close {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .title {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
border-left: 1px solid #bc1150;
|
||||
}
|
||||
.container .column_clients .title span.text {
|
||||
display: none;
|
||||
}
|
||||
.container .column_clients .title span.open, .container .column_clients .title span.close {
|
||||
display: inline;
|
||||
}
|
||||
.container .column_clients .title span.open svg, .container .column_clients .title span.close svg {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
margin: 28% auto auto auto;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.container .column_clients .btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn {
|
||||
display: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.container .column_clients .btn a {
|
||||
flex-basis: 100%;
|
||||
padding: 0.4rem;
|
||||
text-align: center;
|
||||
font-size: 0.9rem;
|
||||
color: #FFFFFF;
|
||||
background-color: #3d3d3d;
|
||||
border-bottom: 1px solid #131313;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn a {
|
||||
display: block;
|
||||
padding: 0.8rem;
|
||||
border-radius: 0px;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.container .column_clients .btn a span {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn a span {
|
||||
display: inline;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
.container .column_clients .btn a:hover {
|
||||
background: #373737;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn:first-of-type {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.container .column_clients .btn:first-of-type a {
|
||||
border-bottom: none;
|
||||
}
|
||||
.theme--default .container .column_clients .btn:first-of-type a {
|
||||
background: #E32A6D;
|
||||
}
|
||||
.theme--dark .container .column_clients .btn:first-of-type a {
|
||||
background: #E32A6D;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn:first-of-type a {
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
}
|
||||
.theme--default .container .column_clients .btn:first-of-type a:hover {
|
||||
background: #bc1150;
|
||||
}
|
||||
.theme--dark .container .column_clients .btn:first-of-type a:hover {
|
||||
background: #bc1150;
|
||||
}
|
||||
.container .column_clients .btn span {
|
||||
flex-basis: 20%;
|
||||
margin-left: 0.4rem;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
.container .column_clients .btn span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
body.profile .column_content {
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.profile .column_content {
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
body.note .column_content {
|
||||
flex-basis: 70%;
|
||||
max-width: 70%;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content {
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
body.note .column_content .profile_intro {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
body.note .column_content .profile_intro a {
|
||||
display: inherit;
|
||||
align-items: inherit;
|
||||
margin: 1rem 0 1rem 0;
|
||||
text-decoration: none;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content .profile_intro a {
|
||||
margin-top: 0rem;
|
||||
margin-bottom: -0.5rem;
|
||||
}
|
||||
}
|
||||
body.note .column_content .profile_intro .info-wrapper {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content .profile_intro .info-wrapper {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content .profile_intro .info-wrapper .name, body.note .column_content .profile_intro .info-wrapper .npub {
|
||||
display: block-inline;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
body.note .column_content .profile_intro .pic-wrapper {
|
||||
flex-basis: 16%;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content .profile_intro .pic-wrapper {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
body.note .column_content .profile_intro .published_at {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
align-self: end;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.theme--default body.note .column_content .profile_intro .published_at {
|
||||
color: #9a9a9a;
|
||||
}
|
||||
.theme--dark body.note .column_content .profile_intro .published_at {
|
||||
color: #F3F3F3;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
body.note .column_content .profile_intro .published_at {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=styles.css.map */
|
||||
1
static/styles.css.map
Normal file
1
static/styles.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["styles.scss"],"names":[],"mappings":";AAoFA;EACC;EACA;EACA;;AACA;EAJD;IAKE;;;;AAGF;EAIC;EACA;;AA9BG;EA2BA;;AA3BA;EA2BA;;AAKF;EADD;IAEE;;;;AAjCC;EAuCA;;AAvCA;EAuCA;;;AAGJ;EACC;EACA;EACA;EACA;EACA;EAIA;EACA;;AApDG;EAiDF;;AAjDE;EAiDF;;AAID;EACC;EACA;EAIA;EACA;EACA;EACA;EACA;;AA/DE;EAyDD;;AAzDC;EAyDD;;AAOD;EAXD;IAYE;IACA;;;;AAKH;EACC;EACA;EACA;EACA;EACA;EAKA;EACA;;AAlFG;EA8EF;;AA9EE;EA8EF;;AAKD;EAZD;IAaE;IACE;IACA;IACA;;;;AAIJ;EACC;;;AAED;EACC;;;AAIA;EACC;;AAED;EACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;;AACA;EAND;IAOE;IACA;IACA;IACA;;;AArHE;EAyHD;;AAzHC;EAyHD;;;AAKH;EACC;EACA;;AACA;EAHD;IAIE;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACC;EACA;EACA;;AACC;EAJF;IAKE;IACE;IACF;;;;AAGF;EACC;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;;AAEC;EANF;IAOE;IACE;;;AAGH;EACC;EACA;;AACA;EAHD;IAIE;IACA;IACA;;;AAED;EACC;;AACA;EAFD;IAGE;IACA;IACA;IACA;IACA;;EACA;IACC;IACA;;EA7LD;IA+LE;;EA/LF;IA+LE;;;AAKJ;EACC;EACA;EACA;;AAvMC;EAyMA;;AAzMA;EAyMA;;AAED;EAPD;IAQE;;;AAIH;EAEC;EACA;EACA;EACA;;AAEA;EACC;;AAxNC;EA2NC;;AA3ND;EA2NC;;AAGF;EACC;;AA/NA;EAiOC;;AAjOD;EAiOC;;AAGF;EAbD;IAcE;;;AAGF;EACC;EACA;EACA;;AA3OC;EA6OA;;AA7OA;EA6OA;;AAED;EACC;;AAED;EAVD;IAWE;;;AAGF;EACC;;AACA;EACC;;AAzPA;EA2PC;;AA3PD;EA2PC;;AAGF;EACC;;AACA;EACC;;AAED;EACC;EACA;EACA;;AAtQD;EAwQE;;AAxQF;EAwQE;;AAED;EACC;EACA;;AA5QF;EA8QG;;AA9QH;EA8QG;;AA9QH;EAiRG;;AAjRH;EAiRG;;AAKJ;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA,YAnWS;EAoWT;EACA;EACA;EACA;;AACA;EAVD;IAWE;IACA;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EAVD;IAWE;IACA;;;AA7TF;EAmUE;;AAnUF;EAmUE;;AAIF;EACC;EACA;;AAGD;EACC;;AAIF;EACC;;AACA;EACC;EACA;;AAGF;EACC;EACA;EACA;;AACA;EACC;EACA;;AA9VD;EAgWE;;AAhWF;EAgWE;;AAhWF;EAqWI;;AArWJ;EAqWI;;AAGJ;EAAU;;AAxWV;EA2WI;;AA3WJ;EA2WI;;AA3WJ;EAgXI;;AAhXJ;EAgXI;;AAIL;EACC;;AACA;EAFD;IAGE;IACA;;EAxXD;IA0XE;;EA1XF;IA0XE;;;AAQL;EACC;EACA;;AACA;EAHD;IAIE;IAEA;IACA;IACA;IACA;;EAEC;IACC;;EAED;IACC;;;AAIH;EACC;EACA;EACA;;AACA;EACC;;AAED;EAPD;IAQE;IACA;IACA;IACA;IACA;IACA;;EACA;IACC;;EAED;IACC;;EACA;IACC;IACA;IACA;IACA;;;AAKJ;EACC;EACA;EACA;;AACA;EAJD;IAKE;IACA;;;AAED;EACC;EACA;EACA;EACA;EACA,OAhgBU;EAigBV,kBA5fU;EA6fV;EACA;EACA;;AACA;EAVD;IAWE;IACA;IACA;IACA;IACA;;;AAED;EACC;;AACA;EAFD;IAGE;IACA,OAhhBQ;;;AAmhBV;EACC,YA9gBS;;AAkhBV;EADD;IAEE;;;AAED;EAIC;;AA7dD;EA2dG;;AA3dH;EA2dG;;AAGF;EALD;IAME;;;AA/dF;EAmeG;;AAneH;EAmeG;;AAKJ;EACC;EACA;EACA,OA7iBU;;AA8iBV;EAJD;IAKE;;;;AASJ;EACC;EACA;;AACA;EAHD;IAIE;IACA;IACA;;;;AAMF;EACC;EACA;;AACA;EAHD;IAIE;IACA;IACA;;;AAED;EACC;EACA;EACA;;AACA;EACC;EACA;EACA;EACA;EACA;;AACA;EAND;IAOE;IACA;;;AAGF;EACC;;AACA;EAFD;IAGE;;;AAGA;EADD;IAEE;IACA;;;AAIH;EACC;EACA;;AACA;EAHD;IAIE;;;AAGF;EACC;EACA;EACA;EACA;;AAhjBA;EAkjBC;;AAljBD;EAkjBC;;AAED;EARD;IASE;;;;AAOL;EACC;EACA","file":"styles.css"}
|
||||
643
static/styles.scss
Normal file
643
static/styles.scss
Normal file
@@ -0,0 +1,643 @@
|
||||
|
||||
$color-base1: #FFFFFF;
|
||||
$color-base2: #FAFAFA;
|
||||
$color-base3: #F3F3F3;
|
||||
$color-base4: #C9C9C9;
|
||||
$color-base5: #9a9a9a;
|
||||
$color-base6: #3d3d3d;
|
||||
$color-base7: #373737;
|
||||
$color-accent1: #E32A6D;
|
||||
$color-accent2: #bc1150;
|
||||
|
||||
$themes: (
|
||||
default: (
|
||||
base1: $color-base1,
|
||||
base2: $color-base2,
|
||||
base3: $color-base3,
|
||||
base4: $color-base4,
|
||||
base5: $color-base5,
|
||||
base6: $color-base6,
|
||||
base7: $color-base7,
|
||||
accent1: $color-accent1,
|
||||
accent2: $color-accent2,
|
||||
bg-up: $color-base1,
|
||||
bg-down: $color-base1,
|
||||
boxed-title: $color-base7,
|
||||
boxed-bg-title: $color-base4,
|
||||
boxed-bg: $color-base3,
|
||||
separator: $color-base3,
|
||||
),
|
||||
dark: (
|
||||
base1: $color-base7,
|
||||
base2: $color-base6,
|
||||
base3: $color-base5,
|
||||
base4: $color-base4,
|
||||
base5: $color-base3,
|
||||
base6: $color-base2,
|
||||
base7: $color-base2,
|
||||
accent1: $color-accent1,
|
||||
accent2: $color-accent2,
|
||||
bg-up: darken($color-base6, 12%),
|
||||
bg-down: darken($color-base7, 12%),
|
||||
boxed-title: $color-base5,
|
||||
boxed-bg-title: darken($color-base6, 14%),
|
||||
boxed-bg: darken($color-base7, 14%),
|
||||
separator: darken($color-base7, 8%),
|
||||
),
|
||||
);
|
||||
|
||||
$base1: 'base1';
|
||||
$base2: 'base2';
|
||||
$base3: 'base3';
|
||||
$base4: 'base4';
|
||||
$base5: 'base5';
|
||||
$base6: 'base6';
|
||||
$base7: 'base7';
|
||||
$accent1: 'accent1';
|
||||
$accent2: 'accent2';
|
||||
$bg-up: 'bg-up';
|
||||
$bg-down: 'bg-down';
|
||||
$boxed-title: 'boxed-title';
|
||||
$boxed-bg-title: 'boxed-bg-title';
|
||||
$boxed-bg: 'boxed-bg';
|
||||
$separator: 'separator';
|
||||
|
||||
$theme-map: null;
|
||||
@mixin themed() {
|
||||
@each $theme, $map in $themes {
|
||||
.theme--#{$theme} & {
|
||||
$theme-map: () !global;
|
||||
@each $key, $submap in $map {
|
||||
$value: map-get(map-get($themes, $theme), '#{$key}');
|
||||
$theme-map: map-merge($theme-map, ($key: $value)) !global;
|
||||
}
|
||||
@content;
|
||||
$theme-map: null !global;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@function t($key) {
|
||||
@return map-get($theme-map, $key);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=styles.css.map */
|
||||
html {
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 19px;
|
||||
font-weight: 300;
|
||||
@media (max-width: 580px) {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
body {
|
||||
@include themed() {
|
||||
color: t($base7);
|
||||
}
|
||||
margin: 0;
|
||||
margin-bottom: 4rem;
|
||||
&.lock {
|
||||
@media (max-width: 580px) {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
a {
|
||||
@include themed() {
|
||||
color: t($base7);
|
||||
}
|
||||
}
|
||||
.background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@include themed() {
|
||||
background: t($bg-up);
|
||||
}
|
||||
overflow: hidden;
|
||||
z-index: -1;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
@include themed() {
|
||||
background: t($bg-down);
|
||||
}
|
||||
width: 140%;
|
||||
height: 100%;
|
||||
transform: rotate(-20deg);
|
||||
transform-origin: bottom;
|
||||
bottom: -40%;
|
||||
@media (max-width: 580px) {
|
||||
width: 200%;
|
||||
bottom: -40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
@include themed() {
|
||||
color: t($base3);
|
||||
// background: t($base3);
|
||||
}
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
@media (max-width: 580px) {
|
||||
position: relative;
|
||||
float: right;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sun {
|
||||
display: none
|
||||
}
|
||||
.moon {
|
||||
display: block
|
||||
}
|
||||
|
||||
.theme--dark {
|
||||
.sun {
|
||||
display: block
|
||||
}
|
||||
.moon {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 1rem 0;
|
||||
justify-content: left;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 1rem auto 1rem auto;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
span {
|
||||
@include themed() {
|
||||
color: t($accent1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pic-wrapper {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
@media (max-width: 580px) {
|
||||
flex-basis: 40%;
|
||||
}
|
||||
img.pic {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
-webkit-clip-path: url(#svg-shape);
|
||||
-moz-clip-path: url(#svg-shape);
|
||||
-o-clip-path: url(#svg-shape);
|
||||
-ms-clip-path: url(#svg-shape);
|
||||
clip-path: url(#svg-shape);
|
||||
}
|
||||
}
|
||||
|
||||
.container_wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
padding: 0 1rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
.nostr_link {
|
||||
flex-basis: 15%;
|
||||
text-align: right;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
width: 70%;
|
||||
justify-content: space-between;
|
||||
gap: 4.8vw;
|
||||
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.columnA {
|
||||
flex-basis: 25%;
|
||||
margin-top: 2rem;
|
||||
@media (max-width: 580px) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0rem;
|
||||
}
|
||||
.info-wrapper {
|
||||
display: none;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
flex-basis: 64%;
|
||||
max-width: 64%;
|
||||
overflow: hidden;
|
||||
font-size: 1.6rem;
|
||||
.display {
|
||||
display: block;
|
||||
font-size: 1.2rem;
|
||||
@include themed() {
|
||||
color: t($base4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.last_update {
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.5rem;
|
||||
text-align: center;
|
||||
@include themed() {
|
||||
color: t($base4);
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.column_content {
|
||||
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
word-wrap: break-word;
|
||||
margin-right: 1vw;
|
||||
|
||||
.info-wrapper {
|
||||
font-size: 1.6rem;
|
||||
.display {
|
||||
@include themed() {
|
||||
color: t($base4);
|
||||
}
|
||||
}
|
||||
.npub {
|
||||
font-size: 1rem;
|
||||
@include themed() {
|
||||
color: t($base4);
|
||||
}
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
height: 6px;
|
||||
width: 30%;
|
||||
margin-left: -0.6rem;
|
||||
@include themed() {
|
||||
background: t($separator);
|
||||
}
|
||||
&.long {
|
||||
width: 50%;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
}
|
||||
.field {
|
||||
margin-bottom: 1.5rem;
|
||||
.label {
|
||||
font-size: 0.8rem;
|
||||
@include themed() {
|
||||
color: t($accent1);
|
||||
}
|
||||
}
|
||||
&.advanced {
|
||||
display: none;
|
||||
&.visible {
|
||||
display: block;
|
||||
}
|
||||
&.boxed {
|
||||
padding: 0 1rem 1rem;
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
@include themed() {
|
||||
background: t($boxed-bg);
|
||||
}
|
||||
.label {
|
||||
padding: 0.2rem 1rem;
|
||||
margin: 0 -1rem;
|
||||
@include themed() {
|
||||
color: t($boxed-title);
|
||||
}
|
||||
@include themed() {
|
||||
background: t($boxed-bg-title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.advanced-switch-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input[type=checkbox]{
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
}
|
||||
|
||||
label:first-of-type {
|
||||
cursor: pointer;
|
||||
text-indent: -9999px;
|
||||
width: 2.6rem;
|
||||
height: 1.2rem;
|
||||
background: $color-base6;
|
||||
display: inline-block;
|
||||
border-radius: 100px;
|
||||
position: relative;
|
||||
margin-right: 0.5rem;
|
||||
@media (max-width: 580px) {
|
||||
width: 3rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
label:first-of-type:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background: #fff;
|
||||
border-radius: 1rem;
|
||||
transition: 0.2s;
|
||||
@media (max-width: 580px) {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
input:checked + label {
|
||||
@include themed() {
|
||||
background: t($accent1);
|
||||
}
|
||||
}
|
||||
|
||||
input:checked + label:first-of-type:after {
|
||||
left: calc(100% - 2px);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
label:first-of-type:active:after {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
}
|
||||
&.content{
|
||||
line-height: 1.4rem;
|
||||
img {
|
||||
max-width: 100%;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
}
|
||||
.json, .data {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
margin-top: 1rem;
|
||||
.key {
|
||||
display: inline-block;
|
||||
margin-top: 0.5rem;
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.last_update {
|
||||
display: none;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
@include themed() {
|
||||
color: t($base4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.column_clients {
|
||||
flex-basis: 25%;
|
||||
margin-top: 2rem;
|
||||
@media (max-width: 580px) {
|
||||
position: fixed;
|
||||
// top: calc(100vh - 4.6rem);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: all 500ms ease-in-out;
|
||||
&.up {
|
||||
.btn {
|
||||
display: block;
|
||||
}
|
||||
.title span.open {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
span.open, span.close {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
border-left: 1px solid #bc1150;
|
||||
span.text {
|
||||
display: none;
|
||||
}
|
||||
span.open, span.close {
|
||||
display: inline;
|
||||
svg {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
margin: 28% auto auto auto;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.8rem;
|
||||
@media (max-width: 580px) {
|
||||
display: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
a {
|
||||
flex-basis: 100%;
|
||||
padding: 0.4rem;
|
||||
text-align: center;
|
||||
font-size: 0.9rem;
|
||||
color: $color-base1;
|
||||
background-color: $color-base6;
|
||||
border-bottom: 1px solid darken($color-base7, 14%);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
padding: 0.8rem;
|
||||
border-radius: 0px;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
}
|
||||
span {
|
||||
display: none;
|
||||
@media (max-width: 580px) {
|
||||
display: inline;
|
||||
color: $color-base1;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: $color-base7;
|
||||
}
|
||||
}
|
||||
&:first-of-type {
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
}
|
||||
a {
|
||||
@include themed() {
|
||||
background: t($accent1);
|
||||
}
|
||||
border-bottom: none;
|
||||
@media (max-width: 580px) {
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
&:hover {
|
||||
@include themed() {
|
||||
background: t($accent2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
span {
|
||||
flex-basis: 20%;
|
||||
margin-left: 0.4rem;
|
||||
color: $color-base1;
|
||||
@media (max-width: 580px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
body.profile {
|
||||
.column_content {
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
@media (max-width: 580px) {
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.note {
|
||||
.column_content {
|
||||
flex-basis: 70%;
|
||||
max-width: 70%;
|
||||
@media (max-width: 580px) {
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
.profile_intro {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
align-items: center;
|
||||
a {
|
||||
display: inherit;
|
||||
align-items: inherit;
|
||||
margin: 1rem 0 1rem 0;
|
||||
text-decoration: none;
|
||||
flex-wrap: wrap;
|
||||
@media (max-width: 580px) {
|
||||
margin-top: -0rem;
|
||||
margin-bottom: -0.5rem;
|
||||
}
|
||||
}
|
||||
.info-wrapper {
|
||||
flex-basis: 80%;
|
||||
@media (max-width: 580px) {
|
||||
display: block;
|
||||
}
|
||||
.name, .npub {
|
||||
@media (max-width: 580px) {
|
||||
display: block-inline;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pic-wrapper {
|
||||
flex-basis: 16%;
|
||||
margin-right: 1rem;
|
||||
@media (max-width: 580px) {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
.published_at {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
align-self: end;
|
||||
font-size: 0.8rem;
|
||||
@include themed() {
|
||||
color: t($base5);
|
||||
}
|
||||
@media (max-width: 580px) {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
43
static/top.html
Normal file
43
static/top.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<div class="top">
|
||||
<a href="https://nostr.com" class="nostr_link">What is <span>nostr</span>?</a>
|
||||
<div class="theme-toggle">
|
||||
<svg aria-hidden="true" data-prefix="fas" class="moon" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M283.211 512c78.962 0 151.079-35.925 198.857-94.792 7.068-8.708-.639-21.43-11.562-19.35-124.203 23.654-238.262-71.576-238.262-196.954 0-72.222 38.662-138.635 101.498-174.394 9.686-5.512 7.25-20.197-3.756-22.23A258.156 258.156 0 0 0 283.211 0c-141.309 0-256 114.511-256 256 0 141.309 114.511 256 256 256z"></path></svg>
|
||||
<svg aria-hidden="true" data-prefix="fas" class="sun" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 160c-52.9 0-96 43.1-96 96s43.1 96 96 96 96-43.1 96-96-43.1-96-96-96zm246.4 80.5l-94.7-47.3 33.5-100.4c4.5-13.6-8.4-26.5-21.9-21.9l-100.4 33.5-47.4-94.8c-6.4-12.8-24.6-12.8-31 0l-47.3 94.7L92.7 70.8c-13.6-4.5-26.5 8.4-21.9 21.9l33.5 100.4-94.7 47.4c-12.8 6.4-12.8 24.6 0 31l94.7 47.3-33.5 100.5c-4.5 13.6 8.4 26.5 21.9 21.9l100.4-33.5 47.3 94.7c6.4 12.8 24.6 12.8 31 0l47.3-94.7 100.4 33.5c13.6 4.5 26.5-8.4 21.9-21.9l-33.5-100.4 94.7-47.3c13-6.5 13-24.7.2-31.1zm-155.9 106c-49.9 49.9-131.1 49.9-181 0-49.9-49.9-49.9-131.1 0-181 49.9-49.9 131.1-49.9 181 0 49.9 49.9 49.9 131.1 0 181z"></path></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleTheme() {
|
||||
const htmlElement = document.documentElement;
|
||||
const isDarkMode = htmlElement.classList.contains('theme--dark');
|
||||
|
||||
// Toggle theme classes on the html element
|
||||
htmlElement.classList.toggle('theme--dark', !isDarkMode);
|
||||
htmlElement.classList.toggle('theme--default', isDarkMode);
|
||||
|
||||
// Save preference in a cookie that expires at the end of the session
|
||||
const expiryDate = new Date();
|
||||
document.cookie = `themePreference=${isDarkMode ? 'light' : 'dark'};`;
|
||||
}
|
||||
|
||||
// Check if the OS prefers dark mode
|
||||
const prefersDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
// Load preference from the cookie if it exists
|
||||
const themePreference = document.cookie.replace(/(?:(?:^|.*;\s*)themePreference\s*\=\s*([^;]*).*$)|^.*$/, '$1');
|
||||
const isDarkMode = themePreference === 'dark' || (themePreference === '' && prefersDarkMode);
|
||||
|
||||
// Apply theme based on the preference
|
||||
const htmlElement = document.documentElement;
|
||||
htmlElement.classList.toggle('theme--dark', isDarkMode);
|
||||
htmlElement.classList.toggle('theme--default', !isDarkMode);
|
||||
|
||||
// Add click event listener to the theme toggle button
|
||||
const themeToggleButton = document.querySelector('.theme-toggle');
|
||||
themeToggleButton.addEventListener('click', toggleTheme);
|
||||
|
||||
// const prefersDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
// if (prefersDarkMode) {
|
||||
// document.documentElement.classList.add('theme--dark');
|
||||
// }
|
||||
</script>
|
||||
88
utils.go
88
utils.go
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
@@ -38,28 +40,28 @@ func generateClientList(code string, event *nostr.Event) []map[string]string {
|
||||
if strings.HasPrefix(code, "nevent") || strings.HasPrefix(code, "note") {
|
||||
return []map[string]string{
|
||||
{"name": "native client", "url": "nostr:" + code},
|
||||
{"name": "snort", "url": "https://snort.social/e/" + code},
|
||||
{"name": "coracle", "url": "https://coracle.social/" + code},
|
||||
{"name": "satellite", "url": "https://satellite.earth/thread/" + event.ID},
|
||||
{"name": "iris", "url": "https://iris.to/" + code},
|
||||
{"name": "yosup", "url": "https://yosup.app/thread/" + event.ID},
|
||||
{"name": "nostr.band", "url": "https://nostr.band/" + code},
|
||||
{"name": "primal", "url": "https://primal.net/thread/" + event.ID},
|
||||
{"name": "nostribe", "url": "https://www.nostribe.com/post/" + event.ID},
|
||||
{"name": "nostrid", "url": "https://web.nostrid.app/note/" + event.ID},
|
||||
{"name": "Snort", "url": "https://Snort.social/e/" + code},
|
||||
{"name": "Coracle", "url": "https://coracle.social/" + code},
|
||||
{"name": "Satellite", "url": "https://satellite.earth/thread/" + event.ID},
|
||||
{"name": "Iris", "url": "https://iris.to/" + code},
|
||||
{"name": "Yosup", "url": "https://yosup.app/thread/" + event.ID},
|
||||
{"name": "Nostr.band", "url": "https://nostr.band/" + code},
|
||||
{"name": "Primal", "url": "https://primal.net/thread/" + event.ID},
|
||||
{"name": "Nostribe", "url": "https://www.nostribe.com/post/" + event.ID},
|
||||
{"name": "Nostrid", "url": "https://web.nostrid.app/note/" + event.ID},
|
||||
}
|
||||
} else if strings.HasPrefix(code, "npub") || strings.HasPrefix(code, "nprofile") {
|
||||
return []map[string]string{
|
||||
{"name": "native client", "url": "nostr:" + code},
|
||||
{"name": "snort", "url": "https://snort.social/p/" + code},
|
||||
{"name": "coracle", "url": "https://coracle.social/" + code},
|
||||
{"name": "satellite", "url": "https://satellite.earth/@" + code},
|
||||
{"name": "iris", "url": "https://iris.to/" + code},
|
||||
{"name": "yosup", "url": "https://yosup.app/profile/" + event.PubKey},
|
||||
{"name": "nostr.band", "url": "https://nostr.band/" + code},
|
||||
{"name": "primal", "url": "https://primal.net/profile/" + event.PubKey},
|
||||
{"name": "nostribe", "url": "https://www.nostribe.com/profile/" + event.PubKey},
|
||||
{"name": "nostrid", "url": "https://web.nostrid.app/account/" + event.PubKey},
|
||||
{"name": "Snort", "url": "https://snort.social/p/" + code},
|
||||
{"name": "Coracle", "url": "https://coracle.social/" + code},
|
||||
{"name": "Satellite", "url": "https://satellite.earth/@" + code},
|
||||
{"name": "Iris", "url": "https://iris.to/" + code},
|
||||
{"name": "Yosup", "url": "https://yosup.app/profile/" + event.PubKey},
|
||||
{"name": "Nostr.band", "url": "https://nostr.band/" + code},
|
||||
{"name": "Primal", "url": "https://primal.net/profile/" + event.PubKey},
|
||||
{"name": "Nostribe", "url": "https://www.nostribe.com/profile/" + event.PubKey},
|
||||
{"name": "Nostrid", "url": "https://web.nostrid.app/account/" + event.PubKey},
|
||||
}
|
||||
} else if strings.HasPrefix(code, "naddr") {
|
||||
return []map[string]string{
|
||||
@@ -114,3 +116,53 @@ func getPreviewStyle(r *http.Request) string {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func BasicFormatting(input string) string {
|
||||
lines := strings.Split(input, "\n")
|
||||
|
||||
var processedLines []string
|
||||
for _, line := range lines {
|
||||
processedLine := ReplaceURLsWithTags(line)
|
||||
processedLines = append(processedLines, processedLine)
|
||||
}
|
||||
|
||||
return strings.Join(processedLines, "<br/>")
|
||||
}
|
||||
|
||||
func ReplaceURLsWithTags(line string) string {
|
||||
|
||||
// Match and replace image URLs with <img> tags
|
||||
imageExtensions := []string{".jpg", ".jpeg", ".png", ".webp", ".gif"}
|
||||
for _, extension := range imageExtensions {
|
||||
regexPattern := fmt.Sprintf(`\s*(https?://\S+%s)\s*`, extension)
|
||||
regex := regexp.MustCompile(regexPattern)
|
||||
matches := regex.FindAllString(line, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
imgTag := fmt.Sprintf(`<img src="%s" alt="">`, strings.ReplaceAll(match, "\n", ""))
|
||||
line = strings.ReplaceAll(line, match, imgTag)
|
||||
return line
|
||||
}
|
||||
}
|
||||
|
||||
// Match and replace npup1, nprofile1, note1, nevent1, etc
|
||||
nostrRegexPattern := `\s*nostr:((npub|note|nevent|nprofile)1[a-z0-9]+)\s*`
|
||||
nostrRegex := regexp.MustCompile(nostrRegexPattern)
|
||||
line = nostrRegex.ReplaceAllStringFunc(line, func(match string) string {
|
||||
submatch := nostrRegex.FindStringSubmatch(match)
|
||||
if len(submatch) < 2 {
|
||||
return match
|
||||
}
|
||||
capturedGroup := submatch[1]
|
||||
first6 := capturedGroup[:6]
|
||||
last6 := capturedGroup[len(capturedGroup)-6:]
|
||||
replacement := fmt.Sprintf(`<a href="/%s">%s</a>`, capturedGroup, first6+"…"+last6)
|
||||
return replacement
|
||||
})
|
||||
|
||||
// Match and replace other URLs with <a> tags
|
||||
otherRegexPattern := `\S*(https?://\S+)\S*`
|
||||
otherRegex := regexp.MustCompile(otherRegexPattern)
|
||||
line = otherRegex.ReplaceAllString(line, `<a href="$1">$1</a>`)
|
||||
return line
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user