diff options
| author | Kyren223 <contact@kyren.codes> | 2026-10-10 03:26:11 +0300 |
|---|---|---|
| committer | Kyren223 <contact@kyren.codes> | 2026-10-10 03:26:11 +0300 |
| commit | 03403186339abb58c5d4a720a5da23ddde66014b (patch) | |
| tree | 8e07c01399750ce32bc11e215090b2b90f920e1b | |
| parent | 068e5fc397b2dc2a5c77687577e0c29c97b4a422 (diff) | |
| -rw-r--r-- | public/styles/fonts/LowresPixel-Regular.woff | bin | 0 -> 10756 bytes | |||
| -rw-r--r-- | public/styles/fonts/LowresPixel.css | 8 | ||||
| -rw-r--r-- | public/styles/fonts/Monocraft.css | 18 | ||||
| -rw-r--r-- | public/styles/main.css | 1 | ||||
| -rw-r--r-- | public/styles/style.css | 28 | ||||
| -rw-r--r-- | website.go | 65 | ||||
| -rw-r--r-- | website.templ | 2 | ||||
| -rw-r--r-- | website_templ.go | 2 |
8 files changed, 118 insertions, 6 deletions
diff --git a/public/styles/fonts/LowresPixel-Regular.woff b/public/styles/fonts/LowresPixel-Regular.woff Binary files differnew file mode 100644 index 0000000..a1b368a --- /dev/null +++ b/public/styles/fonts/LowresPixel-Regular.woff diff --git a/public/styles/fonts/LowresPixel.css b/public/styles/fonts/LowresPixel.css new file mode 100644 index 0000000..ae4f1d3 --- /dev/null +++ b/public/styles/fonts/LowresPixel.css @@ -0,0 +1,8 @@ +@font-face { + font-family: "LowerPixelRegular"; + font-style: normal; + font-weight: normal; + src: + local("LowerPixelRegular"), + url("LowresPixel-Regular.woff") format("woff"); +} diff --git a/public/styles/fonts/Monocraft.css b/public/styles/fonts/Monocraft.css index df2874e..af7b397 100644 --- a/public/styles/fonts/Monocraft.css +++ b/public/styles/fonts/Monocraft.css @@ -3,106 +3,124 @@ src: url("/public/fonts/Monocraft-ExtraLight.ttf") format("truetype"); font-weight: 100; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight-Italic.ttf") format("truetype"); font-weight: 100; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight.ttf") format("truetype"); font-weight: 200; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight-Italic.ttf") format("truetype"); font-weight: 200; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Light.ttf") format("truetype"); font-weight: 300; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Light-Italic.ttf") format("truetype"); font-weight: 300; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft.ttf") format("truetype"); font-weight: 400; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Italic.ttf") format("truetype"); font-weight: 400; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft.ttf") format("truetype"); font-weight: 500; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Italic.ttf") format("truetype"); font-weight: 500; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-SemiBold.ttf") format("truetype"); font-weight: 600; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-SemiBold-Italic.ttf") format("truetype"); font-weight: 600; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Bold.ttf") format("truetype"); font-weight: 700; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Bold-Italic.ttf") format("truetype"); font-weight: 700; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black.ttf") format("truetype"); font-weight: 800; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black-Italic.ttf") format("truetype"); font-weight: 800; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black.ttf") format("truetype"); font-weight: 900; font-style: normal; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black-Italic.ttf") format("truetype"); font-weight: 900; font-style: italic; + size-adjust: 90%; /* Adjust to JetBrainsMono width, 0.6 / 0.6666 = 0.9 */ } diff --git a/public/styles/main.css b/public/styles/main.css index 2c44266..41d7fa2 100644 --- a/public/styles/main.css +++ b/public/styles/main.css @@ -1,6 +1,7 @@ @import "./fonts/Inter/inter.css"; @import "./fonts/JetBrainsMono.css"; @import "./fonts/Monocraft.css"; +@import "./fonts/LowresPixel.css"; @layer theme, base, components, utilities; @import "tailwindcss/theme.css" layer(theme); diff --git a/public/styles/style.css b/public/styles/style.css index 4aff75b..872086f 100644 --- a/public/styles/style.css +++ b/public/styles/style.css @@ -523,108 +523,132 @@ src: url("/public/fonts/Monocraft-ExtraLight.ttf") format("truetype"); font-weight: 100; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight-Italic.ttf") format("truetype"); font-weight: 100; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight.ttf") format("truetype"); font-weight: 200; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-ExtraLight-Italic.ttf") format("truetype"); font-weight: 200; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Light.ttf") format("truetype"); font-weight: 300; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Light-Italic.ttf") format("truetype"); font-weight: 300; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft.ttf") format("truetype"); font-weight: 400; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Italic.ttf") format("truetype"); font-weight: 400; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft.ttf") format("truetype"); font-weight: 500; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Italic.ttf") format("truetype"); font-weight: 500; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-SemiBold.ttf") format("truetype"); font-weight: 600; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-SemiBold-Italic.ttf") format("truetype"); font-weight: 600; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Bold.ttf") format("truetype"); font-weight: 700; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Bold-Italic.ttf") format("truetype"); font-weight: 700; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black.ttf") format("truetype"); font-weight: 800; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black-Italic.ttf") format("truetype"); font-weight: 800; font-style: italic; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black.ttf") format("truetype"); font-weight: 900; font-style: normal; + size-adjust: 90%; } @font-face { font-family: "Monocraft"; src: url("/public/fonts/Monocraft-Black-Italic.ttf") format("truetype"); font-weight: 900; font-style: italic; + size-adjust: 90%; +} +@font-face { + font-family: "LowerPixelRegular"; + font-style: normal; + font-weight: normal; + src: local("LowerPixelRegular"), url("LowresPixel-Regular.woff") format("woff"); } @layer theme, base, components, utilities; @layer theme { @@ -1892,6 +1916,10 @@ --tw-leading: 1.7; line-height: 1.7; } + .leading-\[1\.32\] { + --tw-leading: 1.32; + line-height: 1.32; + } .leading-\[normal\] { --tw-leading: normal; line-height: normal; @@ -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) diff --git a/website.templ b/website.templ index 94242ad..733aca1 100644 --- a/website.templ +++ b/website.templ @@ -183,7 +183,7 @@ templ HomePage(style Style, latestBlog *Blog) { @TerminalBorder("Profile", "", "[--border-py:0.875rem]") { <div class="flex items-center gap-4 h-38"> <img src="/public/favicon.svg" alt="picture" class="h-full object-cover"/> - @CopyPre(sshKey, "shrink-0 text-[0.675rem] leading-[normal]") { + @CopyPre(sshKey, "shrink-0 text-[0.675rem] leading-[1.32]") { { fingerprint } } </div> diff --git a/website_templ.go b/website_templ.go index 0af20ab..ec59c8a 100644 --- a/website_templ.go +++ b/website_templ.go @@ -1025,7 +1025,7 @@ func HomePage(style Style, latestBlog *Blog) templ.Component { } return nil }) - templ_7745c5c3_Err = CopyPre(sshKey, "shrink-0 text-[0.675rem] leading-[normal]").Render(templ.WithChildren(ctx, templ_7745c5c3_Var50), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = CopyPre(sshKey, "shrink-0 text-[0.675rem] leading-[1.32]").Render(templ.WithChildren(ctx, templ_7745c5c3_Var50), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } |
