summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authora73x <[email protected]>2024-08-27 19:43:56 +0100
committera73x <[email protected]>2024-08-27 20:23:18 +0100
commitd38fc83df3824b840f0b3930e4cb7236bdab84b2 (patch)
tree586a7f940291f933ef2a7e05b20dff21ded6d78a
parentcffb105a9ff8ed5d7aa04e5f4097368f6be38b8e (diff)
feat(content): support templating in content
this is tired person code don't write tired person code
-rw-r--r--README4
-rw-r--r--content/index.md38
-rw-r--r--content/posts.md6
-rw-r--r--content/posts/001.md (renamed from posts/001.md)2
-rw-r--r--content/posts/002.md (renamed from posts/002.md)1
-rw-r--r--content/posts/003.md (renamed from posts/003.md)1
-rw-r--r--content/posts/004.md (renamed from posts/004.md)1
-rw-r--r--embed.go4
-rw-r--r--go.mod6
-rw-r--r--go.sum11
-rw-r--r--html/html.go19
-rw-r--r--markdown/markdown.go76
-rw-r--r--pages/pages.go107
-rw-r--r--proxy/Dockerfile16
-rw-r--r--proxy/fly.toml22
-rw-r--r--proxy/nginx.conf14
-rwxr-xr-xproxy/start.sh6
-rw-r--r--templates/default.html5
-rw-r--r--templates/index.html54
-rw-r--r--templates/layouts/_default.html (renamed from templates/layouts/default.html)2
-rw-r--r--templates/post.html6
-rw-r--r--templates/posts.html9
-rw-r--r--web/web.go138
23 files changed, 280 insertions, 268 deletions
diff --git a/README b/README
index ae8fe58..de4eab4 100644
--- a/README
+++ b/README
@@ -1 +1,3 @@
-just enough framework for a site \ No newline at end of file
+just enough framework for a site
+
+my website in a binary. \ No newline at end of file
diff --git a/content/index.md b/content/index.md
new file mode 100644
index 0000000..e42c4d5
--- /dev/null
+++ b/content/index.md
@@ -0,0 +1,38 @@
+---
+title: me
+---
+* backend cloud software engineer
+* lang: go
+* infra: kubernetes
+
+## tidbits
+
+### #go
+
+* layout packages by what they do, not by their abstract type
+* use channels sparingly. write synchronous methods and allow the caller to make it async
+* `append` modifies the underlying slice, you'll only make this mistake once
+* define interfaces where you use them
+* `make([]int, 5)` has a length and capacity of 5. `([]int, 0,5)` has a length of 0 and capacity of 5.
+ `append()` will only do what you want with the latter
+* don't use `init()`
+* TFBO (test, fix, benchmark, optimise)
+* more CPU != more performance
+ more CPU == more Contention
+
+### #git
+
+* `git reflog`
+* `git commit --fixup=<COMMITISH>`
+ `git rebase origin/main --autosquash`
+
+## resources
+
+* [`proc.go`](https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/runtime/proc.go)
+* [proposal: runtime/metrics: define a recommended set of metrics](https://github.com/golang/go/issues/67120)
+
+## books
+
+* [Designing Data Intensive Applications](https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063)
+* [Database Internals](https://www.oreilly.com/library/view/database-internals/9781492040330)
+* [Efficient Go](https://www.oreilly.com/library/view/efficient-go/9781098105709) \ No newline at end of file
diff --git a/content/posts.md b/content/posts.md
new file mode 100644
index 0000000..020e1cc
--- /dev/null
+++ b/content/posts.md
@@ -0,0 +1,6 @@
+---
+title: posts
+---
+{{range .Collections.posts}}
+- [{{.Meta.title}}]({{.Path}})
+{{end}} \ No newline at end of file
diff --git a/posts/001.md b/content/posts/001.md
index 71ece5b..48ea720 100644
--- a/posts/001.md
+++ b/content/posts/001.md
@@ -1,5 +1,6 @@
---
title: "Go Benchmarking"
+tags: posts
---
1. write a benchmark
2. run a benchmark
@@ -7,6 +8,7 @@ title: "Go Benchmarking"
4. optimise
5. run your tests
6. goto 2.
+
## cpuprofile
`go test -test=XXX -bench <regex> -cpuprofile <file>`
diff --git a/posts/002.md b/content/posts/002.md
index 57ac355..8e22144 100644
--- a/posts/002.md
+++ b/content/posts/002.md
@@ -1,5 +1,6 @@
---
title: Go Project Layouts
+tags: posts
---
Do you lay awake at night and consider how to optimally layout your Go project?
diff --git a/posts/003.md b/content/posts/003.md
index 690b215..e19e891 100644
--- a/posts/003.md
+++ b/content/posts/003.md
@@ -1,5 +1,6 @@
---
title: "Levels of Optimisation"
+tags: posts
---
This probably isn't strictly true, but it makes sense to me.
We've got three levels of "optimisation" (assuming your actual design doesn't suck and needs optimising).
diff --git a/posts/004.md b/content/posts/004.md
index 3ce6a82..ebfaad2 100644
--- a/posts/004.md
+++ b/content/posts/004.md
@@ -1,5 +1,6 @@
---
title: "Writing HTTP Handlers"
+tags: posts
---
I'm sharing how I write handlers in Go.
diff --git a/embed.go b/embed.go
index 006db50..e3e27c2 100644
--- a/embed.go
+++ b/embed.go
@@ -6,5 +6,7 @@ import "embed"
//go:embed public/static/*.woff2
//go:embed templates/*.html
//go:embed templates/layouts/*.html
-//go:embed posts/*.md
+//go:embed content/*.md
+//go:embed content/posts/*.md
+
var Content embed.FS
diff --git a/go.mod b/go.mod
index cbefc2e..3cccf13 100644
--- a/go.mod
+++ b/go.mod
@@ -3,8 +3,8 @@ module git.sr.ht/~a73x/home
go 1.22.5
require (
- github.com/yuin/goldmark v1.7.4
- go.abhg.dev/goldmark/frontmatter v0.2.0
+ github.com/adrg/frontmatter v0.2.0
+ github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6
go.uber.org/zap v1.27.0
)
@@ -12,5 +12,5 @@ require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/stretchr/testify v1.9.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
- gopkg.in/yaml.v3 v3.0.1 // indirect
+ gopkg.in/yaml.v2 v2.3.0 // indirect
)
diff --git a/go.sum b/go.sum
index 18c7fcf..fb52c7c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,15 +1,16 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/adrg/frontmatter v0.2.0 h1:/DgnNe82o03riBd1S+ZDjd43wAmC6W35q67NHeLkPd4=
+github.com/adrg/frontmatter v0.2.0/go.mod h1:93rQCj3z3ZlwyxxpQioRKC1wDLto4aXHrbqIsnH9wmE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 h1:ZPy+2XJ8u0bB3sNFi+I72gMEMS7MTg7aZCCXPOjV8iw=
+github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
-github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
-go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw=
-go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
@@ -18,5 +19,7 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/html/html.go b/html/html.go
new file mode 100644
index 0000000..fe1bbee
--- /dev/null
+++ b/html/html.go
@@ -0,0 +1,19 @@
+package html
+
+import (
+ "github.com/gomarkdown/markdown"
+ "github.com/gomarkdown/markdown/html"
+ "github.com/gomarkdown/markdown/parser"
+)
+
+func MDToHTML(md []byte) []byte {
+ extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
+ p := parser.NewWithExtensions(extensions)
+ doc := p.Parse(md)
+
+ htmlFlags := html.CommonFlags
+ opts := html.RendererOptions{Flags: htmlFlags}
+ renderer := html.NewRenderer(opts)
+
+ return markdown.Render(doc, renderer)
+}
diff --git a/markdown/markdown.go b/markdown/markdown.go
new file mode 100644
index 0000000..0924208
--- /dev/null
+++ b/markdown/markdown.go
@@ -0,0 +1,76 @@
+package markdown
+
+import (
+ "bytes"
+ "fmt"
+ "io/fs"
+ "path/filepath"
+ "strings"
+
+ "git.sr.ht/~a73x/home"
+ "github.com/adrg/frontmatter"
+)
+
+type Content struct {
+ Meta map[string]any
+ Body string
+ Path string
+}
+
+func ParseContents() ([]Content, error) {
+ contentFS, err := fs.Sub(home.Content, "content")
+ if err != nil {
+ return nil, fmt.Errorf("no content found: %v", err)
+ }
+ contentFiles, err := glob(contentFS, ".", ".md")
+ if err != nil {
+ return nil, fmt.Errorf("failed to glob: %v", err)
+ }
+
+ res := make([]Content, 0, len(contentFiles))
+ for _, contentFile := range contentFiles {
+ c, err := parseMarkdownFile(contentFS, contentFile)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read markdown file: %v", err)
+ }
+
+ res = append(res, c)
+ }
+
+ return res, nil
+}
+
+func glob(embedded fs.FS, dir string, ext string) ([]string, error) {
+ files := []string{}
+ err := fs.WalkDir(embedded, dir, func(path string, d fs.DirEntry, err error) error {
+ if filepath.Ext(path) == ext {
+ files = append(files, path)
+ }
+ return nil
+ })
+
+ return files, err
+}
+
+func parseMarkdownFile(embedded fs.FS, path string) (Content, error) {
+ input, err := fs.ReadFile(embedded, path)
+ if err != nil {
+ return Content{}, fmt.Errorf("failed to read post: %v", err)
+ }
+
+ matter := map[string]any{}
+ matter["template"] = "default"
+ rest, err := frontmatter.Parse(bytes.NewBuffer(input), &matter)
+ if err != nil {
+ return Content{}, fmt.Errorf("failed to parse frontmatter: %v", err)
+ }
+ path = strings.Replace(path, ".md", "", 1)
+
+ mc := Content{
+ Body: string(rest),
+ Path: path,
+ Meta: matter,
+ }
+
+ return mc, nil
+}
diff --git a/pages/pages.go b/pages/pages.go
new file mode 100644
index 0000000..fbd179a
--- /dev/null
+++ b/pages/pages.go
@@ -0,0 +1,107 @@
+package pages
+
+import (
+ "bytes"
+ "fmt"
+ "text/template"
+
+ "git.sr.ht/~a73x/home"
+ "git.sr.ht/~a73x/home/html"
+ "git.sr.ht/~a73x/home/markdown"
+)
+
+type GlobalState struct {
+ Collections map[string][]markdown.Content
+}
+
+type ParserPair struct {
+ GlobalState
+ markdown.Content
+}
+
+func renderTemplate(config GlobalState, content markdown.Content) (string, error) {
+ tmpl := content.Meta["template"]
+ chosenTemplate := fmt.Sprintf("templates/%s.html", tmpl)
+ t, err := template.ParseFS(home.Content, chosenTemplate, "templates/layouts/*.html")
+ if err != nil {
+ return "", fmt.Errorf("failed to parse layouts: %v", err)
+ }
+
+ contentParser, err := template.New("content").Parse(string(content.Body))
+ if err != nil {
+ return "", fmt.Errorf("failed parsing content: %v", err)
+ }
+
+ data := ParserPair{
+ config,
+ content,
+ }
+
+ newContent := &bytes.Buffer{}
+ if err := contentParser.Execute(newContent, data); err != nil {
+ return "", fmt.Errorf("failed to execute content template: %v", err)
+ }
+
+ data.Body = string(html.MDToHTML(newContent.Bytes()))
+
+ b := &bytes.Buffer{}
+ if err := t.Execute(b, data); err != nil {
+ return "", err
+ }
+
+ return b.String(), nil
+}
+
+type Page struct {
+ Path string
+ Content string
+}
+
+func Collect() ([]Page, error) {
+ contents, err := markdown.ParseContents()
+ if err != nil {
+ return nil, err
+ }
+
+ gs := GlobalState{
+ Collections: map[string][]markdown.Content{
+ "all": contents,
+ },
+ }
+
+ for _, content := range contents {
+ tags, ok := content.Meta["tags"]
+ if !ok {
+ continue
+ }
+
+ switch tags := tags.(type) {
+ case string:
+ gs.Collections[tags] = append(gs.Collections[tags], content)
+ case []string:
+ for _, tag := range tags {
+ gs.Collections[tag] = append(gs.Collections[tag], content)
+ }
+ }
+ }
+
+ pages := []Page{}
+ for _, content := range contents {
+ page, err := renderTemplate(gs, content)
+ if err != nil {
+ return nil, fmt.Errorf("failed to build site: %v", err)
+ }
+
+ path := content.Path
+ if path == "index" {
+ path = ""
+ }
+
+ pages = append(pages, Page{
+ Path: path,
+ Content: page,
+ })
+ }
+
+ return pages, nil
+}
diff --git a/proxy/Dockerfile b/proxy/Dockerfile
deleted file mode 100644
index 012092d..0000000
--- a/proxy/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM nginx:1.27.0-alpine
-
-RUN apk update && apk add ca-certificates iptables ip6tables && rm -rf /var/cache/apk/*
-
-COPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscaled /app/tailscaled
-COPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscale /app/tailscale
-RUN mkdir -p /var/run/tailscale /var/cache/tailscale /var/lib/tailscale
-
-WORKDIR /app/
-
-COPY nginx.conf /etc/nginx/conf.d/nginx.conf
-COPY /start.sh /app/start.sh
-
-RUN chmod +x /app/start.sh
-
-CMD ["/app/start.sh"]
diff --git a/proxy/fly.toml b/proxy/fly.toml
deleted file mode 100644
index 97bf7b5..0000000
--- a/proxy/fly.toml
+++ /dev/null
@@ -1,22 +0,0 @@
-# fly.toml app configuration file generated for home-divine-bush-1861 on 2024-08-11T17:34:11+01:00
-#
-# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
-#
-
-app = 'home-divine-bush-1861'
-primary_region = 'lhr'
-
-[build]
-
-[http_service]
- internal_port = 8080
- force_https = true
- auto_stop_machines = 'stop'
- auto_start_machines = true
- min_machines_running = 0
- processes = ['app']
-
-[[vm]]
- memory = '1gb'
- cpu_kind = 'shared'
- cpus = 1
diff --git a/proxy/nginx.conf b/proxy/nginx.conf
deleted file mode 100644
index 4095372..0000000
--- a/proxy/nginx.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-server {
- listen 8080;
- listen [::]:8080;
-
- server_name a73x.sh;
-
-
- location / {
- proxy_ssl_session_reuse off;
- proxy_ssl_server_name on;
- proxy_pass https://home.folk-amberjack.ts.net/;
- proxy_set_header X-Forwarded-Host $http_host;
- }
-}
diff --git a/proxy/start.sh b/proxy/start.sh
deleted file mode 100755
index c2c73d6..0000000
--- a/proxy/start.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-/app/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/var/run/tailscale/tailscaled.sock &
-/app/tailscale up --authkey=${TAILSCALE_AUTHKEY} --hostname=fly-app
-
-nginx -g "daemon off;"
diff --git a/templates/default.html b/templates/default.html
new file mode 100644
index 0000000..3d68d2c
--- /dev/null
+++ b/templates/default.html
@@ -0,0 +1,5 @@
+{{template "base" .}}
+{{define "content"}}
+<h1>{{.Meta.title}}</h1>
+{{ .Body }}
+{{end}} \ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
deleted file mode 100644
index e84a09e..0000000
--- a/templates/index.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{{template "base" .}}
-{{define "content"}}
- <ul>
- <li>backend cloud software engineer</li>
- <li>lang: go</li>
- <li>infra: kubernetes</li>
- </ul>
- <h2>tidbits</h2>
- <h3>#go</h3>
- <ul>
- <li>layout packages by what they do, not by their abstract type</li>
- <li>use channels sparingly. write synchronous methods and allow the caller to make it async</li>
- <li><code>append</code> modifies the underlying slice, you'll only make this mistake once</li>
- <li>define interfaces where you use them</li>
- <li><code>make([]int, 5)</code> has a length and capacity of 5. <code>([]int, 0,5)</code> has a length
- of 0 and capacity of 5.
- <br />
- <code>append()</code> will only do what you want with the latter
- </li>
- <li>don't use <code>init()</code></li>
- <li>TFBO (test, fix, benchmark, optimise)</li>
- <li>more CPU != more performance
- <br/>
- more CPU == more Contention
- </li>
- </ul>
- <h3>#git</h3>
- <ul>
- <li><code>git reflog</code></li>
- <li><code>git commit --fixup=&lt;COMMITISH&gt;</code>
- <br />
- <code>git rebase origin/main --autosquash</code>
- </li>
- </ul>
-
- <h2>resources</h2>
- <ul>
- <li><a href=https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/runtime/proc.go><code>proc.go</code></a></li>
- <li><a href=https://github.com/golang/go/issues/67120>proposal: runtime/metrics: define a recommended set of metrics</a></li>
- </ul>
- <h2>books</h2>
- <ul>
- <li><a href=https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063 />Designing
- Data Intensive Applications</a></li>
- <li><a href=https://www.oreilly.com/library/view/database-internals/9781492040330 />Database Internals
- </a>
- </li>
- <li>
- <a href=https://www.oreilly.com/library/view/efficient-go/9781098105709 /> Efficient Go</a>
-
- </li>
-
- </ul>
-{{end}}
diff --git a/templates/layouts/default.html b/templates/layouts/_default.html
index 14868cf..beab01e 100644
--- a/templates/layouts/default.html
+++ b/templates/layouts/_default.html
@@ -61,7 +61,7 @@
<nav>
<ul>
<li><a href="/">home</a></li>
- <li><a href="/posts.html">posts</a></li>
+ <li><a href="/posts">posts</a></li>
</ul>
</nav>
{{ template "content" . }}
diff --git a/templates/post.html b/templates/post.html
deleted file mode 100644
index 0a6cc6e..0000000
--- a/templates/post.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{{template "base" .}}
-{{define "content"}}
-<h1>{{.Title}}</h1>
-{{ .Post }}
-{{end}}
-
diff --git a/templates/posts.html b/templates/posts.html
deleted file mode 100644
index c68fb73..0000000
--- a/templates/posts.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{{template "base" .}}
-{{define "content"}}
-<h1>posts</h1>
-<ul>
- {{range .Posts}}
- <li><a href="{{.Path}}">{{.Title}}</a></li>
-{{end}}
-</ul>
-{{end}}
diff --git a/web/web.go b/web/web.go
index 487dd81..e421d3c 100644
--- a/web/web.go
+++ b/web/web.go
@@ -1,138 +1,16 @@
package web
import (
- "bytes"
"fmt"
- "io"
"io/fs"
"net/http"
- "path/filepath"
- "strings"
- "text/template"
"time"
"git.sr.ht/~a73x/home"
- "github.com/yuin/goldmark"
- "github.com/yuin/goldmark/parser"
- "go.abhg.dev/goldmark/frontmatter"
+ "git.sr.ht/~a73x/home/pages"
"go.uber.org/zap"
)
-type CommonData struct {
- Posts []PostData
-}
-
-type PostData struct {
- Title string
- Path string
-}
-
-func GeneratePosts(mux *http.ServeMux) ([]PostData, error) {
- converter := goldmark.New(
- goldmark.WithExtensions(
- &frontmatter.Extender{},
- ))
-
- t, err := template.ParseFS(home.Content, "templates/layouts/*.html")
- if err != nil {
- return nil, fmt.Errorf("failed to parse layouts: %v", err)
- }
-
- final := []PostData{}
- posts, err := fs.Glob(home.Content, "posts/*.md")
- if err != nil {
- return nil, fmt.Errorf("failed to glob posts: %v", err)
- }
-
- for _, post := range posts {
- postName := filepath.Base(post)
- postName = strings.Split(postName, ".")[0] + ".html"
-
- // parse markdown
- input, err := fs.ReadFile(home.Content, post)
- if err != nil {
- return nil, fmt.Errorf("failed to read post: %v", err)
- }
-
- var b bytes.Buffer
- ctx := parser.NewContext()
- if err := converter.Convert(input, &b, parser.WithContext(ctx)); err != nil {
- return nil, err
- }
-
- d := frontmatter.Get(ctx)
- var meta map[string]string
- if err := d.Decode(&meta); err != nil {
- return nil, err
- }
-
- foo, err := t.ParseFS(home.Content, "templates/post.html")
- if err != nil {
- return nil, fmt.Errorf("failed to parse post template: %v", err)
- }
-
- content, err := io.ReadAll(&b)
- if err != nil {
- return nil, fmt.Errorf("failed to read post template: %v", err)
- }
-
- type IPostData struct {
- Title string
- Post string
- }
-
- mux.HandleFunc("/posts/"+postName, func(w http.ResponseWriter, r *http.Request) {
- if err := foo.ExecuteTemplate(w, "post.html", IPostData{
- Title: meta["title"],
- Post: string(content),
- }); err != nil {
- fmt.Println(err)
- }
- })
-
- final = append(final, PostData{
- Title: meta["title"],
- Path: "posts/" + postName,
- })
- }
-
- return final, nil
-}
-
-func loadTemplates(mux *http.ServeMux, data any) error {
- tmplFiles, err := fs.ReadDir(home.Content, "templates")
- if err != nil {
- return fmt.Errorf("failed to parse template layouts")
- }
-
- for _, tmpl := range tmplFiles {
- if tmpl.IsDir() {
- continue
- }
-
- pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html")
- if err != nil {
- return fmt.Errorf("failed to parse template "+tmpl.Name(), err)
- }
-
- if tmpl.Name() == "index.html" {
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- pt.ExecuteTemplate(w, tmpl.Name(), data)
- })
- } else if tmpl.Name() == "page.html" {
- continue
- } else {
- mux.HandleFunc("/"+tmpl.Name(), func(w http.ResponseWriter, r *http.Request) {
- pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html")
- if err != nil {
- fmt.Printf("failed to parse template "+tmpl.Name(), err)
- }
- pt.ExecuteTemplate(w, tmpl.Name(), data)
- })
- }
- }
- return nil
-}
func New(logger *zap.Logger) (*http.Server, error) {
loggingMiddleware := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -148,17 +26,15 @@ func New(logger *zap.Logger) (*http.Server, error) {
}
mux := http.NewServeMux()
- postData, err := GeneratePosts(mux)
+ pages, err := pages.Collect()
if err != nil {
- return nil, fmt.Errorf("failed to generate posts: %v", err)
- }
-
- data := CommonData{
- Posts: postData,
+ return nil, err
}
- if err := loadTemplates(mux, data); err != nil {
- return nil, fmt.Errorf("failed to parse templates: %v", err)
+ for _, page := range pages {
+ mux.HandleFunc("GET /"+page.Path, func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte(page.Content))
+ })
}
staticFs, err := fs.Sub(home.Content, "public/static")