main soggy/glerc / ssg / page.go
  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}