summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile2
-rw-r--r--Makefile20
-rw-r--r--cmd/generate/main.go44
-rw-r--r--cmd/home/main.go132
-rw-r--r--embed.go4
-rw-r--r--go.mod12
-rw-r--r--go.sum12
-rw-r--r--posts/001.md35
-rw-r--r--public/index.html99
-rw-r--r--public/posts.html59
-rw-r--r--templates/index.html2
-rw-r--r--templates/layouts/default.html3
-rw-r--r--templates/layouts/header.html5
-rw-r--r--templates/post.html5
-rw-r--r--templates/posts.html7
15 files changed, 218 insertions, 223 deletions
diff --git a/Dockerfile b/Dockerfile
index 672c4e9..0ec734d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,7 @@ COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
-RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/app ./...
+RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/app ./cmd/home/
FROM scratch
diff --git a/Makefile b/Makefile
index d791247..83d165e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,18 @@
-.PHONY: fly
+VERSION=0.0.1
+DOCKER_IMAGE=alexemery/home:${VERSION}
+.PHONY: fly
fly:
cd proxy && fly deploy
-.PHONY: content
-content:
- go run ./cmd/generate
-
-.PHONY: serve
-serve: content
+.PHONY: serve
+serve:
go run ./cmd/home
+
+.PHONY: image
+image:
+ docker build . -t ${DOCKER_IMAGE}
+
+.PHONY: public
+public: image
+ docker push ${DOCKER_IMAGE}
diff --git a/cmd/generate/main.go b/cmd/generate/main.go
deleted file mode 100644
index a739fea..0000000
--- a/cmd/generate/main.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "path/filepath"
- "text/template"
-)
-
-func Run() error {
- t, err := template.ParseGlob("./templates/layouts/*.html")
- // t, err := template.ParseFiles("index.html", "header.html")
- if err != nil {
- return fmt.Errorf("Failed to parse layouts: %v", err)
- }
-
- for _, page := range []string{"index.html", "posts.html"} {
- file, err := os.Create(filepath.Join("public", page))
- if err != nil {
- return fmt.Errorf("Failed to create file: %v", err)
- }
-
- defer file.Close()
-
- foo, err := t.ParseFiles("./templates/" + page)
- if err != nil {
- return fmt.Errorf("Parse template file: %v", err)
- }
-
- err = foo.ExecuteTemplate(file, "index.html", nil)
- if err != nil {
- return fmt.Errorf("Failed to generate file: %v", err)
- }
- }
-
- return nil
-
-}
-func main() {
- if err := Run(); err != nil {
- log.Fatal(err)
- }
-}
diff --git a/cmd/home/main.go b/cmd/home/main.go
index f284c30..01bddee 100644
--- a/cmd/home/main.go
+++ b/cmd/home/main.go
@@ -1,15 +1,131 @@
package main
import (
+ "bytes"
+ "fmt"
+ "io"
"io/fs"
"log"
"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"
"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)
+ }
+
+ mux.HandleFunc("/posts/"+postName, func(w http.ResponseWriter, r *http.Request) {
+ if err := foo.ExecuteTemplate(w, "post.html", 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 main() {
logger, _ := zap.NewProduction()
loggingMiddleware := func(next http.Handler) http.Handler {
@@ -26,13 +142,25 @@ func main() {
}
mux := http.NewServeMux()
+ postData, err := GeneratePosts(mux)
+ data := CommonData{
+ Posts: postData,
+ }
+
+ if err != nil {
+ log.Fatal("failed to generate posts", err)
+ }
+
+ if err := loadTemplates(mux, data); err != nil {
+ log.Fatal("failed to parse templates", err)
+ }
- staticFs, err := fs.Sub(home.Content, "public")
+ staticFs, err := fs.Sub(home.Content, "public/static")
if err != nil {
log.Fatal(err)
}
- mux.Handle("GET /", http.FileServer(http.FS(staticFs)))
+ mux.Handle("GET /static", http.FileServer(http.FS(staticFs)))
server := http.Server{
Addr: ":8080",
diff --git a/embed.go b/embed.go
index 182ede2..c111372 100644
--- a/embed.go
+++ b/embed.go
@@ -3,5 +3,7 @@ package home
import "embed"
//go:embed public/static/*.woff2
-//go:embed public/*.html
+//go:embed templates/*.html
+//go:embed templates/layouts/*.html
+//go:embed posts/*.md
var Content embed.FS
diff --git a/go.mod b/go.mod
index f7db60e..c283353 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,14 @@ module git.sr.ht/~a73x/home
go 1.22.5
-require go.uber.org/zap v1.27.0
+require (
+ github.com/yuin/goldmark v1.7.4
+ go.abhg.dev/goldmark/frontmatter v0.2.0
+ go.uber.org/zap v1.27.0
+)
-require go.uber.org/multierr v1.10.0 // indirect
+require (
+ github.com/BurntSushi/toml v1.2.1 // indirect
+ go.uber.org/multierr v1.10.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
index 2d29b57..9d9984a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,14 +1,22 @@
+github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
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/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.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+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=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
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.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/posts/001.md b/posts/001.md
new file mode 100644
index 0000000..9942c2f
--- /dev/null
+++ b/posts/001.md
@@ -0,0 +1,35 @@
+---
+title: "Go Benchmarking"
+---
+## Benchmarking
+1. write a benchmark
+2. run a benchmark
+3. get a profile
+4. optimise
+5. run your tests
+6. goto 2.
+### cpuprofile
+`go test -test=XXX -bench <regex> -cpuprofile <file>`
+
+### memprofile
+`go test -test=XXX -bench <regex> -memprofile <file> -benchmem`
+
+### pprof
+[pprof usage](https://github.com/google/pprof/blob/main/doc/README.md)
+
+`go pprof -http=:8080 profile.pb.gz`
+will show a web UI for analysing the profile.
+
+#### views:
+- flame graph: `localhost:8080/ui/flamegraph`
+ - shows percentage breakdown of how much resource each "call" made.
+ - clicking a box will make it "100%" allowing for deep diving
+ - right click "show source code" to view
+- top: `localhost:8080/ui/top`
+ - shows top functions
+ - `flat`: profile samples in this function
+ - `cum`: (cumulative) profile samples in this function and its callees
+- source: `localhost:8080/ui/source`
+ - each source line is annotated with the time spent in that source line
+ - the first number does not count time spent in functions called from the source line
+ - the second number does \ No newline at end of file
diff --git a/public/index.html b/public/index.html
deleted file mode 100644
index 61413a8..0000000
--- a/public/index.html
+++ /dev/null
@@ -1,99 +0,0 @@
-
-<!DOCTYPE html>
-<html lang="en">
-
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="description" content="Home for a73x" />
- <meta name="author" content="a73x" />
- <meta name="viewport"
- content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" />
- <title>a73x</title>
- <style>
- @font-face {
- font-family: 'Mono';
- src: url('./static/V1-ServerMono-Regular.woff2') format('woff2');
- font-weight: normal;
- font-style: normal;
- }
-
- body {
- font-family: "Mono";
- }
-
- code {
- font-family: "Mono";
- color: crimson;
- background-color: #f1f1f1;
- padding: 2px;
- }
-
- nav ul {
- display: flex;
- list-style: none;
- }
-
- nav ul li {
- margin-right: 20px;
- }
- </style>
-</head>
-
-<body>
- <!-- templates/header.html -->
-<h1>a73x</h1>
-<nav>
- <ul>
- <li><a href="/">Home</a></li>
- <li><a href="/posts">Posts</a></li>
- </ul>
-</nav>
-
-
- <ul>
- <li>backend cloud software engineer</li>
- <li>lang: go</li>
- <li>infra: kubernetes</li>
- </ul>
- <h2>daily learnings</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>
- </ul>
- <h3>#git</h3>
- <ul>
- <li><code>git commit --fixup=&lt;COMMITSH&gt;</code>
- <br />
- <code>git rebase origin/main --autosquash</code>
- </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>
-
-</body>
-
-</html>
-
-
diff --git a/public/posts.html b/public/posts.html
deleted file mode 100644
index b63f4da..0000000
--- a/public/posts.html
+++ /dev/null
@@ -1,59 +0,0 @@
-
-<!DOCTYPE html>
-<html lang="en">
-
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="description" content="Home for a73x" />
- <meta name="author" content="a73x" />
- <meta name="viewport"
- content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" />
- <title>a73x</title>
- <style>
- @font-face {
- font-family: 'Mono';
- src: url('./static/V1-ServerMono-Regular.woff2') format('woff2');
- font-weight: normal;
- font-style: normal;
- }
-
- body {
- font-family: "Mono";
- }
-
- code {
- font-family: "Mono";
- color: crimson;
- background-color: #f1f1f1;
- padding: 2px;
- }
-
- nav ul {
- display: flex;
- list-style: none;
- }
-
- nav ul li {
- margin-right: 20px;
- }
- </style>
-</head>
-
-<body>
- <!-- templates/header.html -->
-<h1>a73x</h1>
-<nav>
- <ul>
- <li><a href="/">Home</a></li>
- <li><a href="/posts">Posts</a></li>
- </ul>
-</nav>
-
-
-<h1>Posts</h1>
-
-</body>
-
-</html>
-
-
diff --git a/templates/index.html b/templates/index.html
index ee1a64c..8f07cc0 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -28,7 +28,7 @@
</li>
</ul>
- <h2>Books</h2>
+ <h2>books</h2>
<ul>
<li><a href=https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063 />Designing
Data Intensive Applications</a></li>
diff --git a/templates/layouts/default.html b/templates/layouts/default.html
index cfb0c17..5c8bf64 100644
--- a/templates/layouts/default.html
+++ b/templates/layouts/default.html
@@ -12,12 +12,13 @@
<style>
@font-face {
font-family: 'Mono';
- src: url('./static/V1-ServerMono-Regular.woff2') format('woff2');
+ src: url('/static/V1-ServerMono-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
body {
+ max-width: 70ch;
font-family: "Mono";
}
diff --git a/templates/layouts/header.html b/templates/layouts/header.html
index be02def..f1d2d18 100644
--- a/templates/layouts/header.html
+++ b/templates/layouts/header.html
@@ -1,8 +1,7 @@
-<!-- templates/header.html -->
<h1>a73x</h1>
<nav>
<ul>
- <li><a href="/">Home</a></li>
- <li><a href="/posts">Posts</a></li>
+ <li><a href="/">home</a></li>
+ <li><a href="/posts.html">posts</a></li>
</ul>
</nav>
diff --git a/templates/post.html b/templates/post.html
new file mode 100644
index 0000000..69c17e2
--- /dev/null
+++ b/templates/post.html
@@ -0,0 +1,5 @@
+{{template "base" .}}
+{{define "content"}}
+{{ . }}
+{{end}}
+
diff --git a/templates/posts.html b/templates/posts.html
index 75d3801..c68fb73 100644
--- a/templates/posts.html
+++ b/templates/posts.html
@@ -1,4 +1,9 @@
{{template "base" .}}
{{define "content"}}
-<h1>Posts</h1>
+<h1>posts</h1>
+<ul>
+ {{range .Posts}}
+ <li><a href="{{.Path}}">{{.Title}}</a></li>
+{{end}}
+</ul>
{{end}}