refactor(pages): use html instead of json to render custom pages

This commit is contained in:
Anhgelus Morhtuuzh 2025-03-10 11:14:09 +01:00
parent 2d74d8afc3
commit 42a96cbb6e
No known key found for this signature in database
GPG key ID: CAD341EFA92DDDE5
4 changed files with 60 additions and 102 deletions

View file

@ -88,22 +88,7 @@
] ]
}, },
"content": { "content": {
"type": "array", "type": "string"
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"content": {
"type": "string"
}
},
"required": [
"type",
"content"
]
}
} }
}, },
"required": [ "required": [

123
data.go
View file

@ -3,11 +3,9 @@ package main
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/anhgelus/golatt" "github.com/anhgelus/golatt"
"html/template" "html/template"
"log/slog"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -26,6 +24,7 @@ type ConfigData interface {
GetTextColor() template.CSS GetTextColor() template.CSS
GetBackground() template.CSS GetBackground() template.CSS
GetBackgroundImage() template.CSS GetBackgroundImage() template.CSS
IsCustomPage() bool
} }
type Config struct { type Config struct {
@ -91,22 +90,30 @@ func (c *Config) GetTextColor() template.CSS {
return c.Color.GetTextColor() return c.Color.GetTextColor()
} }
func (c *Config) IsCustomPage() bool {
return false
}
var legalContent template.HTML
func (c *Config) GetLegal() (template.HTML, error) {
if legalContent == "" {
b, err := os.ReadFile(c.Legal)
if err != nil {
return "", err
}
legalContent = template.HTML(b)
}
return legalContent, nil
}
type CustomPage struct { type CustomPage struct {
Title string `json:"title" toml:"title"` Title string `json:"title" toml:"title"`
URI string `json:"uri" toml:"uri"` URI string `json:"uri" toml:"uri"`
Image string `json:"image" toml:"image"` Image string `json:"image" toml:"image"`
Description string `json:"description" toml:"description"` Description string `json:"description" toml:"description"`
Color *Color `json:"colors" toml:"colors"` Color *Color `json:"colors" toml:"colors"`
Content []*CustomContent `json:"content" toml:"content"` Content string `json:"content" toml:"content"`
}
type CustomContent struct {
Type string `json:"type" toml:"type"`
Content string `json:"content" toml:"content"`
}
type Content interface {
Get() template.HTML
} }
func (c *Config) LoadCustomPages() ([]*CustomPage, error) { func (c *Config) LoadCustomPages() ([]*CustomPage, error) {
@ -136,19 +143,6 @@ func (c *Config) LoadCustomPages() ([]*CustomPage, error) {
return pages, nil return pages, nil
} }
var legalContent template.HTML
func (c *Config) GetLegal() (template.HTML, error) {
if legalContent == "" {
b, err := os.ReadFile(c.Legal)
if err != nil {
return "", err
}
legalContent = template.HTML(b)
}
return legalContent, nil
}
func (t *Color) GetTextColor() template.CSS { func (t *Color) GetTextColor() template.CSS {
return template.CSS("--text-color: " + t.Text + ";") return template.CSS("--text-color: " + t.Text + ";")
} }
@ -189,64 +183,21 @@ func (p *CustomPage) GetBackground() template.CSS {
return p.Color.GetBackground() return p.Color.GetBackground()
} }
func (p *CustomPage) GetContent() template.HTML { func (p *CustomPage) IsCustomPage() bool {
var res template.HTML return true
for _, c := range p.Content {
res += c.Get(p)
}
return res
} }
func (c *CustomContent) Get(p *CustomPage) template.HTML { var contentsMap = map[string]template.HTML{}
if c.Type == TitleContentType {
return template.HTML("<h2>" + c.Content + "</h2>") func (p *CustomPage) GetContent() (template.HTML, error) {
} else if c.Type == SubtitleContentType { res, ok := contentsMap[p.URI]
return template.HTML("<h3>" + c.Content + "</h3>") if !ok {
} else if c.Type == ParagraphContentType { b, err := os.ReadFile(p.Content)
return template.HTML("<p>" + c.Content + "</p>") if err != nil {
} else if c.Type == ListContentType { return "", err
v := ""
for _, s := range strings.Split(c.Content, "--") {
if len(strings.Trim(s, " ")) == 0 {
continue
}
v += "<li>" + strings.Trim(s, " ") + "</li>"
} }
return template.HTML("<ul>" + v + "</ul>") res = template.HTML(b)
} else if c.Type == OrderedListContentType { contentsMap[p.URI] = res
v := ""
for _, s := range strings.Split(c.Content, "--") {
if len(strings.TrimSpace(s)) == 0 {
continue
}
v += "<li>" + strings.TrimSpace(s) + "</li>"
}
return template.HTML("<ol>" + v + "</ol>")
} else if c.Type == ButtonsContentType {
// [Bonsoir](/hello) -- [Bonjour](/not_hello)
v := ""
for _, s := range strings.Split(c.Content, "--") {
if len(strings.TrimSpace(s)) == 0 {
continue
}
sp := strings.Split(s, "](")
if len(sp) != 2 {
slog.Warn("Invalid button", "s", s)
continue
}
url := strings.TrimSpace(sp[1])
v += fmt.Sprintf(
`<div class="link"><a href="%s">%s</a></div>`,
url[:len(url)-1],
strings.TrimSpace(sp[0])[1:],
)
}
return template.HTML(fmt.Sprintf(
`<nav class="links" style="%s">%s</nav>`,
p.Color.Button.GetBackground()+p.Color.Button.GetTextColor(),
v,
))
} }
slog.Warn("Unknown type", "type", c.Type, "value", c.Content) return res, nil
return ""
} }

View file

@ -8,6 +8,11 @@
<title>{{ .Title }}</title> <title>{{ .Title }}</title>
<link rel="stylesheet" href="{{getAssetPath "styles.css"}}" /> <link rel="stylesheet" href="{{getAssetPath "styles.css"}}" />
{{template "opengraph-base" .SEO}} {{template "opengraph-base" .SEO}}
{{ if .Data.IsCustomPage }}
<style>
.links { {{ .Data.Color.Button.GetBackground }}{{ .Data.Color.Button.GetTextColor }} }
</style>
{{ end }}
</head> </head>
<body style="{{ .Data.GetBackgroundImage }}{{ .Data.GetTextColor }}"> <body style="{{ .Data.GetBackgroundImage }}{{ .Data.GetTextColor }}">
<div class="center"> <div class="center">

17
test.html Normal file
View file

@ -0,0 +1,17 @@
<h2>Hello</h2>
<p>world, what's up?</p>
<h3>Sed proin quis cursus do lobortis ultricies viverra tempus et.</h3>
<p>Lectus pulvinar lorem mi enim pharetra sed aliqua et cursus. Sit sem ut elit amet labore lectus sed at vulputate.</p>
<nav class="links">
<div class="link">
<a href="/">home sweet home</a>
</div>
<div class="link">
<a href="https://www.steampowered.com">steam</a>
</div>
</nav>
<ul>
<li>Hello 1</li>
<li>Not hello 2</li>
<li>Final element 3</li>
</ul>