diff options
Diffstat (limited to 'website.go')
| -rw-r--r-- | website.go | 65 |
1 files changed, 61 insertions, 4 deletions
@@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "html" "html/template" "io/fs" "log" @@ -25,7 +26,7 @@ import ( "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" - "github.com/yuin/goldmark/renderer/html" + gmhtml "github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/text" "github.com/yuin/goldmark/util" "gopkg.in/yaml.v3" @@ -189,12 +190,39 @@ var md = goldmark.New( }), ), ), - goldmark.WithRendererOptions(html.WithUnsafe()), + goldmark.WithRendererOptions(gmhtml.WithUnsafe()), goldmark.WithParserOptions( parser.WithASTTransformers(util.Prioritized(externalLinks{}, 100)), ), ) +var tagRe = regexp.MustCompile(`<[^>]*>`) + +func ligatures(html string) string { + var out strings.Builder + depth, last := 0, 0 + apply := func(s string) string { + if depth == 0 { + return arrows.Replace(s) + } + return s + } + for _, loc := range tagRe.FindAllStringIndex(html, -1) { + out.WriteString(apply(html[last:loc[0]])) + tag := html[loc[0]:loc[1]] + switch { + case strings.HasPrefix(tag, "<pre"), strings.HasPrefix(tag, "<code"): + depth++ + case strings.HasPrefix(tag, "</pre"), strings.HasPrefix(tag, "</code"): + depth-- + } + out.WriteString(tag) + last = loc[1] + } + out.WriteString(apply(html[last:])) + return out.String() +} + type frontmatter struct { Title string `yaml:"title"` Desc string `yaml:"description"` @@ -234,7 +262,7 @@ func parseBlog(name, raw string) (Blog, error) { if err := md.Convert([]byte(body), &buf); err != nil { return Blog{}, err } - HTML := buf.String() + HTML := ligatures(buf.String()) slug := strings.TrimSuffix(name, ".md") date := frontmatter.Date // frontmatter wins @@ -321,6 +349,33 @@ func latestBlog(blogs []Blog) *Blog { type externalLinks struct{} +func newReplacer(pairs map[string]string) *strings.Replacer { + keys := make([]string, 0, len(pairs)) + for k := range pairs { + keys = append(keys, k) + } + slices.SortFunc(keys, func(a, b string) int { return cmp.Compare(len(b), len(a)) }) + + args := make([]string, 0, len(keys)*2) + for _, k := range keys { + args = append(args, html.EscapeString(k), pairs[k]) // rendered text has < and > escaped + } + return strings.NewReplacer(args...) +} + +var arrows = newReplacer(map[string]string{ + // arrows + "->": "→", "<-": "←", "<->": "↔", + "-->": "⟶", "<--": "⟵", "<-->": "⟷", + "->>": "↠", "<<-": "↞", "|->": "↦", + "~>": "↝", "<~": "↜", + // double arrows + "=>": "⇒", "<=>": "⇔", + "==>": "⟹", "<==": "⟸", "<==>": "⟺", + // comparisons + ">=": "≥", "<=": "≤", "!=": "≠", "+-": "±", +}) + func openInNewTab(n ast.Node) { n.SetAttributeString("target", []byte("_blank")) n.SetAttributeString("rel", []byte("noopener noreferrer")) @@ -376,6 +431,7 @@ var projects = []Project{ Icon: IconCpu("text-[#F16265]"), Tags: []ProjectTag{ {"Zig", Color("text-[#D8C44B]")}, + {"Raylib", Color("text-[#FFFFFF]")}, }, Links: []ProjectLink{ {IconGit("text-[#F5A670]"), "Git", "https://git.kyren.codes/kyren/cpu-vs-ai.git"}, @@ -602,7 +658,8 @@ func main() { minecraft := FontPack{ Monospace: `Monocraft, JetBrains Mono, monospace`, - Normal: `Monocraft, Inter, system-ui, sans-serif`, + // Normal: `Inter, Lower Pixel Regular, Monocraft, system-ui, sans-serif`, + Normal: `LowerPixelRegular, Inter, system-ui, sans-serif`, } SetTheme("carbonight-cat", carbonightCat) |
