aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hergès <anhgelus@anhgelus.world>2024-12-10 20:47:56 +0100
committerGitHub <noreply@github.com>2024-12-10 20:47:56 +0100
commit0149f9905c2830441d9ccfeccbb02e4ebf60a0d8 (patch)
tree52ffaeaea8534a2f4771a2c8a353b37f6a97f566
parent730ec347582289efbc0cd1c48e4c243d4c4920d6 (diff)
parent40fe301b5462b84e06747ff30add26b4259d38a4 (diff)
Merge pull request #1 from anhgelus/feat/custom-page
[Feat] Custom page
-rw-r--r--config.schema.json (renamed from schema.json)3
-rw-r--r--custom_page.schema.json117
-rw-r--r--data.go172
-rw-r--r--index.ts5
-rw-r--r--main.go15
-rw-r--r--scss/main.scss19
-rw-r--r--templates/page/custom_page.gohtml11
7 files changed, 323 insertions, 19 deletions
diff --git a/schema.json b/config.schema.json
index 2678ecf..9b325c3 100644
--- a/schema.json
+++ b/config.schema.json
@@ -176,6 +176,9 @@
"image",
"tags"
]
+ },
+ "custom_pages": {
+ "type": "array"
}
},
"additionalProperties": false,
diff --git a/custom_page.schema.json b/custom_page.schema.json
new file mode 100644
index 0000000..c7a1907
--- /dev/null
+++ b/custom_page.schema.json
@@ -0,0 +1,117 @@
+{
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "uri": {
+ "type": "string"
+ },
+ "image": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "colors": {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string"
+ },
+ "tag_hover": {
+ "type": "string"
+ },
+ "background": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "angle": {
+ "type": "number"
+ },
+ "colors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "type": "string"
+ },
+ "position": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "color",
+ "position"
+ ]
+ }
+ }
+ },
+ "required": [
+ "type",
+ "angle",
+ "colors"
+ ]
+ },
+ "buttons": {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string"
+ },
+ "text_hover": {
+ "type": "string"
+ },
+ "background": {
+ "type": "string"
+ },
+ "background_hover": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "text",
+ "text_hover",
+ "background",
+ "background_hover"
+ ]
+ }
+ },
+ "required": [
+ "text",
+ "tag_hover",
+ "background",
+ "buttons"
+ ]
+ },
+ "content": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "content": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "content"
+ ]
+ }
+ }
+ },
+ "required": [
+ "title",
+ "uri",
+ "image",
+ "description",
+ "colors",
+ "content"
+ ]
+} \ No newline at end of file
diff --git a/data.go b/data.go
index 49df295..ad51683 100644
--- a/data.go
+++ b/data.go
@@ -1,18 +1,39 @@
package main
import (
+ "encoding/json"
+ "fmt"
"github.com/anhgelus/golatt"
"html/template"
+ "log/slog"
+ "os"
"strconv"
+ "strings"
)
+const (
+ TitleContentType = "title"
+ SubtitleContentType = "subtitle"
+ ParagraphContentType = "paragraph"
+ ListContentType = "list"
+ OrderedListContentType = "ordered_list"
+ ButtonsContentType = "links"
+)
+
+type ConfigData interface {
+ GetTextColor() template.CSS
+ GetBackground() template.CSS
+ GetBackgroundImage() template.CSS
+}
+
type Config struct {
- Image string `json:"image"`
- Description string `json:"description"`
- Person *Person `json:"person"`
- Color *Color `json:"colors"`
- Links []*Link `json:"links"`
- Legal *Legal `json:"legal"`
+ Image string `json:"image"`
+ Description string `json:"description"`
+ Person *Person `json:"person"`
+ Color *Color `json:"colors"`
+ Links []*Link `json:"links"`
+ Legal *Legal `json:"legal"`
+ CustomPages []string `json:"custom_pages"`
}
type Person struct {
@@ -63,7 +84,62 @@ type Legal struct {
}
func (c *Config) GetBackground() template.CSS {
- bg := c.Color.Background
+ return c.Color.GetBackground()
+}
+
+func (c *Config) GetBackgroundImage() template.CSS {
+ return template.CSS("--background-image: url(" + golatt.GetStaticPath(c.Image) + ");")
+}
+
+func (c *Config) GetTextColor() template.CSS {
+ return c.Color.GetTextColor()
+}
+
+type CustomPage struct {
+ Title string `json:"title"`
+ URI string `json:"uri"`
+ Image string `json:"image"`
+ Description string `json:"description"`
+ Color *Color `json:"colors"`
+ Content []*CustomContent `json:"content"`
+}
+
+type CustomContent struct {
+ Type string `json:"type"`
+ Content string `json:"content"`
+}
+
+type Content interface {
+ Get() template.HTML
+}
+
+func (c *Config) LoadCustomPages() ([]*CustomPage, error) {
+ if c.CustomPages == nil {
+ println("null")
+ return nil, nil
+ }
+ var pages []*CustomPage
+ for _, cp := range c.CustomPages {
+ b, err := os.ReadFile(cp)
+ if err != nil {
+ return nil, err
+ }
+ var p CustomPage
+ err = json.Unmarshal(b, &p)
+ if err != nil {
+ return nil, err
+ }
+ pages = append(pages, &p)
+ }
+ return pages, nil
+}
+
+func (t *Color) GetTextColor() template.CSS {
+ return template.CSS("--text-color: " + t.Text + ";")
+}
+
+func (t *Color) GetBackground() template.CSS {
+ bg := t.Background
css := "background: " + bg.Type + "-gradient("
if bg.Type == "linear" {
css += strconv.Itoa(int(bg.Angle)) + "deg,"
@@ -74,14 +150,6 @@ func (c *Config) GetBackground() template.CSS {
return template.CSS(css[:len(css)-1] + ");")
}
-func (c *Config) GetBackgroundImage() template.CSS {
- return template.CSS("--background-image: url(" + golatt.GetStaticPath(c.Image) + ");")
-}
-
-func (c *Config) GetTextColor() template.CSS {
- return template.CSS("--text-color: " + c.Color.Text + ";")
-}
-
func (b *ButtonColor) GetTextColor() template.CSS {
return template.CSS("--text-color: " + b.Text + ";--text-color-hover: " + b.TextHover + ";")
}
@@ -93,3 +161,77 @@ func (b *ButtonColor) GetBackground() template.CSS {
func (t *Color) GetTagColor() template.CSS {
return template.CSS("--tag-hover: " + t.TagHover + ";")
}
+
+func (p *CustomPage) GetTextColor() template.CSS {
+ return p.Color.GetTextColor()
+}
+
+func (p *CustomPage) GetBackgroundImage() template.CSS {
+ return template.CSS("--background-image: url(" + golatt.GetStaticPath(p.Image) + ");")
+}
+
+func (p *CustomPage) GetBackground() template.CSS {
+ return p.Color.GetBackground()
+}
+
+func (p *CustomPage) GetContent() template.HTML {
+ var res template.HTML
+ for _, c := range p.Content {
+ res += c.Get(p)
+ }
+ return res
+}
+
+func (c *CustomContent) Get(p *CustomPage) template.HTML {
+ if c.Type == TitleContentType {
+ return template.HTML("<h2>" + c.Content + "</h2>")
+ } else if c.Type == SubtitleContentType {
+ return template.HTML("<h3>" + c.Content + "</h3>")
+ } else if c.Type == ParagraphContentType {
+ return template.HTML("<p>" + c.Content + "</p>")
+ } else if c.Type == ListContentType {
+ 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>")
+ } else if c.Type == OrderedListContentType {
+ 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 ""
+}
diff --git a/index.ts b/index.ts
index 24951c2..c3f46b0 100644
--- a/index.ts
+++ b/index.ts
@@ -23,10 +23,7 @@ function changePage(href: string) {
const doc = new DOMParser().parseFromString(html, "text/html")
window.history.pushState({}, "", href)
document.title = doc.title
- const distMain = doc.querySelector("main")
- const currentMain = document.querySelector("main")
- if (distMain === null || currentMain === null) document.body = doc.body
- else currentMain.innerHTML = distMain.innerHTML
+ document.body = doc.body
setupEvents()
scrollTo({
top: 0,
diff --git a/main.go b/main.go
index 57ef485..34086cc 100644
--- a/main.go
+++ b/main.go
@@ -50,6 +50,10 @@ func main() {
if err != nil {
panic(err)
}
+ customPages, err := cfg.LoadCustomPages()
+ if err != nil {
+ panic(err)
+ }
g := golatt.New(templates)
g.DefaultSeoData = &golatt.SeoData{
Image: cfg.Image,
@@ -74,6 +78,17 @@ func main() {
&cfg).
Handle()
+ for _, cp := range customPages {
+ slog.Info("Creating custom page...", "title", cp.Title, "uri", cp.URI)
+ g.NewTemplate("custom_page",
+ cp.URI,
+ cp.Title,
+ cp.Image,
+ cp.Description,
+ cp).
+ Handle()
+ }
+
g.NotFoundHandler = func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}
diff --git a/scss/main.scss b/scss/main.scss
index bd22152..bef8c81 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -236,3 +236,22 @@ h4 {
padding: 0 2rem 1rem 2rem;
border-radius: 32px;
}
+
+.custom-page {
+ & h2 {
+ margin-bottom: 1rem;
+ }
+ & h3 {
+ margin-bottom: 0.5rem;
+ }
+ & ul {
+ list-style: disc inside;
+ }
+ & .links {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+}
diff --git a/templates/page/custom_page.gohtml b/templates/page/custom_page.gohtml
new file mode 100644
index 0000000..83a4983
--- /dev/null
+++ b/templates/page/custom_page.gohtml
@@ -0,0 +1,11 @@
+{{define "body"}}
+ <main class="custom-page" style="{{ .GetBackground }}">
+ <div class="header">
+ <h2>{{ .Title }}</h2>
+ <nav>
+ <a href="/">Home</a>
+ </nav>
+ </div>
+ {{ .GetContent }}
+ </main>
+{{end}}