main.go

on kitten's pastes | raw

expires: 21 Jun, 2024

  1package main
  2
  3import (
  4	"bytes"
  5	"encoding/base64"
  6	"errors"
  7	"os"
  8	"strings"
  9	"path/filepath"
 10
 11	"github.com/yuin/goldmark"
 12	"github.com/yuin/goldmark/extension"
 13	"github.com/yuin/goldmark/parser"
 14	"github.com/yuin/goldmark/renderer/html"
 15)
 16
 17type badge struct {
 18	Path string
 19	Link string
 20}
 21
 22type badges []badge
 23
 24func parseBadge(name string) (badge, error) {
 25	parts := strings.Split(name, "_")
 26	if len(parts) != 2 {
 27		return badge{}, errors.New("invalid badge name")
 28	}
 29
 30	link, err := base64.StdEncoding.DecodeString(
 31		parts[1][:strings.Index(parts[1], filepath.Ext(parts[1]))])
 32	if err != nil {
 33		return badge{}, err
 34	}
 35
 36	return badge{
 37		Path: name,
 38		Link: string(link),
 39	}, nil
 40}
 41
 42func (b badge) String() (html string) {
 43	if b.Link != "" {
 44		html += `<a href="`+b.Link+`">`
 45	}
 46	html += `<img src="`+b.Path+`" alt="`+filepath.Base(b.Path)+`"></a>`
 47	return
 48}
 49
 50func parseBadges(names []string) (badges, error) {
 51	var bs badges
 52	for _, n := range names {
 53		b, err := parseBadge(n)
 54		if err != nil {
 55			return nil, err
 56		}
 57		bs = append(bs, b)
 58	}
 59	return bs, nil
 60}
 61
 62func (bs badges) String() (html string) {
 63	for i, b := range bs {
 64		html += "\n" + b.String()
 65		if i == len(bs)-1 {
 66			html += "\n"
 67		}
 68	}
 69	return
 70}
 71
 72func main() {
 73	md := goldmark.New(
 74		goldmark.WithExtensions(extension.GFM),
 75		goldmark.WithParserOptions(
 76			parser.WithAutoHeadingID(),
 77		),
 78		goldmark.WithRendererOptions(
 79			html.WithHardWraps(),
 80			html.WithXHTML(),
 81		),
 82	)
 83
 84	bsrcs, err := filepath.Glob("badges/*.gif")
 85	if err != nil {
 86		panic(err)
 87	}
 88
 89	badges, err := parseBadges(bsrcs)
 90	if err != nil {
 91		panic(err)
 92	}
 93
 94	srcs, err := filepath.Glob("*.md")
 95	if err != nil {
 96		panic(err)
 97	}
 98
 99	var nav strings.Builder
100	nav.WriteString("<nav>\n")
101	for i, src := range srcs {
102		to := strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
103		nav.WriteString(`<a href="`+to+`.html">`+to+`</a>`)
104		if i != len(srcs)-1 {
105			nav.WriteString(` <span class="sep">|</span>`)
106		}
107		nav.WriteString("\n")
108	}
109	nav.WriteString("</nav>")
110
111	for _, src := range srcs {
112		dst := strings.TrimSuffix(src, filepath.Ext(src))
113		name := filepath.Base(dst)
114		dst += ".html"
115
116		data, err := os.ReadFile(src)
117		if err != nil {
118			panic(err)
119		}
120
121		buf := bytes.NewBuffer([]byte(`<!DOCTYPE html>
122<html lang="en">
123<head>
124<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
125<meta name="viewport" content="width=device-width, initial-scale=1.0">
126<link href="style.css" rel="stylesheet" type="text/css" media="all">
127<title>` + name + `</title>
128</head>
129<body>
130` + nav.String() + `
131<hr>
132`))
133
134		if err := md.Convert(data, buf); err != nil {
135			panic(err)
136		}
137
138		if name == "index" {
139			buf.Write([]byte("<footer>" + badges.String() + "</footer>\n"))
140		}
141
142		buf.Write([]byte("</body>\n</html>"))
143
144		if err := os.WriteFile(dst, buf.Bytes(), 0o644); err != nil {
145			panic(err)
146		}
147	}
148}