1package ssg
2
3import (
4 "bytes"
5 "io"
6 "io/fs"
7 "log/slog"
8 "os"
9 "path/filepath"
10 "strings"
11
12 "github.com/yuin/goldmark"
13 "github.com/yuin/goldmark-meta"
14 "github.com/yuin/goldmark/parser"
15)
16
17type PageError int
18
19const (
20 _ PageError = iota
21 NonExistentTemplate
22)
23
24func (e PageError) Error() string {
25 switch e {
26 case NonExistentTemplate:
27 return "given template does not exist"
28 }
29 panic("this should not be reached")
30}
31
32func GetPages(dir string) (map[string]string, error) {
33 res := make(map[string]string, 0)
34 err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
35 if err != nil {
36 slog.Error("got err while reading path", "path", path, "err", err)
37 return filepath.SkipDir
38 }
39 if !d.IsDir() && strings.HasSuffix(path, ".md") {
40 content, err := os.ReadFile(path)
41 if err != nil {
42 slog.Error("got err while reading file", "file", path, "err", err)
43 return filepath.SkipDir
44 }
45 res[path] = string(content)
46 }
47 return nil
48 })
49 if err != nil {
50 return res, err
51 }
52 return res, nil
53}
54
55func BuildPage(w io.Writer, name string, path string, page string, markdown goldmark.Markdown, templates Templates, config Config, baseUrl string, sidebar []SidebarItem) error {
56 var buff bytes.Buffer
57 ctx := parser.NewContext()
58 if err := markdown.Convert([]byte(page), &buff, parser.WithContext(ctx)); err != nil {
59 return err
60 }
61 frontmatter := meta.Get(ctx)
62 var templateName string
63 switch v := frontmatter["template"]; v {
64 case nil:
65 if name == "index" {
66 templateName = "index"
67 } else {
68 templateName = "page"
69 }
70 default:
71 templateName = v.(string)
72 }
73 if baseUrl == "" {
74 baseUrl = config.BaseURL
75 }
76 var title string
77 switch v := frontmatter["title"]; v {
78 case nil:
79 title = config.Title
80 default:
81 title = v.(string)
82 }
83 var description string
84 switch v := frontmatter["description"]; v {
85 case nil:
86 description = config.Description
87 default:
88 description = v.(string)
89 }
90 templateData := TemplateData{
91 Title: title,
92 Description: description,
93 BaseURL: baseUrl,
94 Params: frontmatter,
95 Config: config,
96 Content: buff.String(),
97 Sidebar: sidebar,
98 }
99 if err := BuildTemplate(w, name, templates[templateName], templateData); err != nil {
100 return err
101 }
102 return nil
103}