summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/generator/generator_test.go64
-rw-r--r--internal/generator/templates/themes/volcano/FONT_LICENSE.txt59
-rw-r--r--internal/generator/templates/themes/volcano/bebas-neue-v16-latin_latin-ext-regular.woff2bin0 -> 17144 bytes
-rw-r--r--internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-600.woff2bin0 -> 52452 bytes
-rw-r--r--internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-regular.woff2bin0 -> 50696 bytes
-rw-r--r--internal/generator/templates/themes/volcano/theme.css37
6 files changed, 155 insertions, 5 deletions
diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go
index 10116a2..62b3593 100644
--- a/internal/generator/generator_test.go
+++ b/internal/generator/generator_test.go
@@ -443,6 +443,70 @@ func TestRun_writesPagesAndAtom(t *testing.T) {
}
}
+func TestRun_writesVolcanoFontAssets(t *testing.T) {
+ t.Parallel()
+
+ out := t.TempDir()
+ postDir := filepath.Join(out, "posts", "a1")
+ if err := os.MkdirAll(postDir, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ p := &post.Post{
+ ID: "a1",
+ Timestamp: time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC),
+ PostType: post.TypeText,
+ Content: "<p>volcano</p>",
+ }
+ if err := p.Save(postDir); err != nil {
+ t.Fatal(err)
+ }
+
+ cfg := &config.Config{
+ OutputDir: out,
+ BaseURL: "https://example.test",
+ Theme: "volcano",
+ }
+ if err := Run(ctx, cfg); err != nil {
+ t.Fatalf("Run: %v", err)
+ }
+
+ themeDir := filepath.Join(out, "themes", "volcano")
+ for _, name := range []string{
+ "bebas-neue-v16-latin_latin-ext-regular.woff2",
+ "inter-v20-latin_latin-ext-regular.woff2",
+ "inter-v20-latin_latin-ext-600.woff2",
+ "FONT_LICENSE.txt",
+ } {
+ info, err := os.Stat(filepath.Join(themeDir, name))
+ if err != nil {
+ t.Fatalf("%s: %v", name, err)
+ }
+ if info.Size() == 0 {
+ t.Fatalf("%s is empty", name)
+ }
+ }
+
+ css, err := os.ReadFile(filepath.Join(themeDir, "theme.css"))
+ if err != nil {
+ t.Fatalf("read volcano theme.css: %v", err)
+ }
+ got := string(css)
+ for _, localFont := range []string{
+ "url('bebas-neue-v16-latin_latin-ext-regular.woff2')",
+ "url('inter-v20-latin_latin-ext-regular.woff2')",
+ "url('inter-v20-latin_latin-ext-600.woff2')",
+ } {
+ if !strings.Contains(got, localFont) {
+ t.Fatalf("volcano theme.css missing local font reference %q", localFont)
+ }
+ }
+ for _, forbidden := range []string{"googleapis", "gstatic", "fonts.cdn", "@import url(http"} {
+ if strings.Contains(got, forbidden) {
+ t.Fatalf("volcano theme.css contains forbidden external font reference %q", forbidden)
+ }
+ }
+}
+
func TestWritePage(t *testing.T) {
t.Parallel()
diff --git a/internal/generator/templates/themes/volcano/FONT_LICENSE.txt b/internal/generator/templates/themes/volcano/FONT_LICENSE.txt
new file mode 100644
index 0000000..82df777
--- /dev/null
+++ b/internal/generator/templates/themes/volcano/FONT_LICENSE.txt
@@ -0,0 +1,59 @@
+Volcano theme fonts
+===================
+
+This directory bundles the web fonts:
+
+ bebas-neue-v16-latin_latin-ext-regular.woff2 (weight 400)
+ inter-v20-latin_latin-ext-regular.woff2 (weight 400)
+ inter-v20-latin_latin-ext-600.woff2 (weight 600)
+
+Subsets: latin, latin-ext.
+
+Source / version
+----------------
+- Bebas Neue family page : https://fonts.google.com/specimen/Bebas+Neue
+- Bebas Neue designer : Ryoichi Tsunekawa
+- Bebas Neue webfont set : bebas-neue-v16 (latin + latin-ext, woff2)
+- Bebas Neue upstream source : https://github.com/dharmatype/Bebas-Neue
+- Bebas Neue metadata commit : 686d14af640c17af3691c597778f121d840d9051
+- Bebas Neue last modified : 2025-09-16
+- Bebas Neue fetched via : https://gwfh.mranftl.com/fonts/bebas-neue
+- Bebas Neue download URL : https://gwfh.mranftl.com/api/fonts/bebas-neue?download=zip&subsets=latin,latin-ext&formats=woff2&variants=regular
+- Inter family page : https://fonts.google.com/specimen/Inter
+- Inter designer : Rasmus Andersson
+- Inter webfont set : inter-v20 (latin + latin-ext, woff2)
+- Inter upstream source : https://www.github.com/rsms/inter
+- Inter metadata commit : 66647c0bbbe41a850d79d9c76fb13add3378940f
+- Inter archive source : https://github.com/rsms/inter/files/15438431/Inter-4.1-GoogleFonts.zip
+- Inter last modified : 2025-09-10
+- Inter fetched via : https://gwfh.mranftl.com/fonts/inter
+- Inter download URL : https://gwfh.mranftl.com/api/fonts/inter?download=zip&subsets=latin,latin-ext&formats=woff2&variants=regular,600
+- Fetched on : 2026-05-01
+
+License
+-------
+SIL Open Font License, Version 1.1.
+
+Bebas Neue copyright:
+Copyright 2019 The Bebas Neue Project Authors
+(https://github.com/dharmatype/Bebas-Neue).
+
+Inter copyright:
+Copyright 2020 The Inter Project Authors
+(https://github.com/rsms/inter).
+
+ - Summary : https://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web
+ - Full text : https://openfontlicense.org/open-font-license-official-text/
+
+The OFL allows free use, modification, and redistribution of the font,
+including embedding in commercial products. Any standalone modified
+version of the font itself must be released under the same license and
+must not use the Reserved Font Names "Bebas Neue" or "Inter".
+
+Required attribution
+--------------------
+Font: "Bebas Neue" by Ryoichi Tsunekawa - https://github.com/dharmatype/Bebas-Neue
+ Licensed under the SIL Open Font License 1.1.
+
+Font: "Inter" by Rasmus Andersson - https://github.com/rsms/inter
+ Licensed under the SIL Open Font License 1.1.
diff --git a/internal/generator/templates/themes/volcano/bebas-neue-v16-latin_latin-ext-regular.woff2 b/internal/generator/templates/themes/volcano/bebas-neue-v16-latin_latin-ext-regular.woff2
new file mode 100644
index 0000000..924acb6
--- /dev/null
+++ b/internal/generator/templates/themes/volcano/bebas-neue-v16-latin_latin-ext-regular.woff2
Binary files differ
diff --git a/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-600.woff2 b/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-600.woff2
new file mode 100644
index 0000000..283b13a
--- /dev/null
+++ b/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-600.woff2
Binary files differ
diff --git a/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-regular.woff2 b/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-regular.woff2
new file mode 100644
index 0000000..70dd51e
--- /dev/null
+++ b/internal/generator/templates/themes/volcano/inter-v20-latin_latin-ext-regular.woff2
Binary files differ
diff --git a/internal/generator/templates/themes/volcano/theme.css b/internal/generator/templates/themes/volcano/theme.css
index 83c80df..44c1c2e 100644
--- a/internal/generator/templates/themes/volcano/theme.css
+++ b/internal/generator/templates/themes/volcano/theme.css
@@ -1,14 +1,41 @@
+ /* Self-hosted web fonts: Bebas Neue by Ryoichi Tsunekawa and Inter by
+ Rasmus Andersson (SIL OFL 1.1).
+ Sources: https://fonts.google.com/specimen/Bebas+Neue and
+ https://fonts.google.com/specimen/Inter
+ See FONT_LICENSE.txt in this directory. */
+ @font-face {
+ font-family: 'Bebas Neue';
+ src: url('bebas-neue-v16-latin_latin-ext-regular.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+ }
+ @font-face {
+ font-family: 'Inter';
+ src: url('inter-v20-latin_latin-ext-regular.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+ }
+ @font-face {
+ font-family: 'Inter';
+ src: url('inter-v20-latin_latin-ext-600.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+ }
:root { --lava:#ff4400; --ember:#ff8c00; --hot:#ffcc00; --bg:#0d0802; }
* { margin:0; padding:0; box-sizing:border-box; }
- body { font-family:'Segoe UI',system-ui,sans-serif; background:var(--bg);
+ body { font-family:'Inter','Segoe UI',system-ui,sans-serif; background:var(--bg);
color:#ffe8cc; overflow:hidden; height:100vh; height:100dvh; }
+ h1, h2, h3, h4, h5, h6 { font-family:'Bebas Neue','Segoe UI',system-ui,sans-serif; font-weight:400; letter-spacing:0.08em; }
#three-canvas { position:fixed; top:0; left:0; width:100%; height:100%; z-index:1; }
.overlay { position:relative; z-index:10; height:100vh; height:100dvh; display:flex; flex-direction:column; }
header { padding:16px 28px; background:rgba(13,8,2,0.82); backdrop-filter:blur(12px);
border-bottom:1px solid rgba(255,68,0,0.3); display:flex; align-items:center; justify-content:space-between; }
.logo { display:flex; align-items:center; gap:14px; }
- .logo-mark { font-size:2rem; font-weight:800; color:var(--ember); text-shadow:0 0 16px var(--lava); }
- .logo-title h1 { font-size:1.5rem; font-weight:700; color:#ffe8cc; }
+ .logo-mark { font-family:'Bebas Neue','Segoe UI',system-ui,sans-serif; font-size:2rem; font-weight:400; color:var(--ember); text-shadow:0 0 16px var(--lava); }
+ .logo-title h1 { font-family:'Bebas Neue','Segoe UI',system-ui,sans-serif; font-size:1.5rem; font-weight:400; color:#ffe8cc; letter-spacing:0.08em; }
.logo-title .subtitle { font-size:0.75rem; color:rgba(255,232,204,0.5); margin-top:2px; }
.logo-title .subtitle a { color:var(--ember); text-decoration:none; }
.logo-title .subtitle a:hover { text-shadow:0 0 8px var(--lava); }
@@ -37,7 +64,7 @@
.post:hover { border-color:var(--ember); box-shadow:0 0 20px rgba(255,68,0,0.25); transform:translateY(-2px); }
.post-active { border-color:var(--hot) !important; background:rgba(30,8,2,0.9) !important;
box-shadow:0 0 24px rgba(255,140,0,0.4),inset 3px 0 0 var(--hot) !important; }
- .post-header { display:flex; justify-content:space-between; margin-bottom:12px; font-size:0.88rem; }
+ .post-header { display:flex; justify-content:space-between; margin-bottom:12px; font-size:0.88rem; font-weight:600; }
.post-time { color:var(--ember); font-family:monospace; font-size:0.8rem; }
.post-text { line-height:1.65; font-size:0.95rem; }
.post-text a { color:var(--ember); text-decoration:none; }
@@ -62,7 +89,7 @@
box-shadow: 0 0 20px var(--lava), 0 6px 30px rgba(255,68,0,0.4);
}
@keyframes splashEmberPulse { from { opacity:0.6; transform: scaleX(0.9); } to { opacity:1; transform: scaleX(1); } }
- [data-sno-theme="volcano"] .splash-title { font-size:clamp(1.45rem,4.5vw,2rem); color:#ffe8cc;
+ [data-sno-theme="volcano"] .splash-title { font-family:'Bebas Neue','Segoe UI',system-ui,sans-serif; font-size:clamp(1.45rem,4.5vw,2rem); font-weight:400; letter-spacing:0.08em; color:#ffe8cc;
text-shadow:0 0 20px var(--lava); }
[data-sno-theme="volcano"] .splash-tag { color:var(--ember); letter-spacing:0.15em; }
[data-sno-theme="volcano"] .splash-hint { color:rgba(255,232,204,0.88); }