summaryrefslogtreecommitdiff
path: root/website.go
diff options
context:
space:
mode:
Diffstat (limited to 'website.go')
-rw-r--r--website.go65
1 files changed, 61 insertions, 4 deletions
diff --git a/website.go b/website.go
index b54030c..e64e7f8 100644
--- a/website.go
+++ b/website.go
@@ -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)