summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-18 23:14:09 +0300
committerPaul Buetow <paul@buetow.org>2026-04-18 23:14:09 +0300
commit7fc2aca9a97894f28c3cc52aab0ad919dcb3eb27 (patch)
tree4d891975e1a96f9dadbae67d19207f033d47270f
parentc96b991081fa56aad043f39ab85c4862db7d86d6 (diff)
fix(generator): match markdown typography between list and zoomed-in modal views
The zoomed-in post modal (opened with Enter/click) used #modal-content to display post HTML, but the CSS typography rules (.post-text p/ul/ol/li margin and padding) only targeted the .post-text class used in the list view. This caused visually different formatting — missing paragraph spacing and unindented lists — in the expanded modal compared to the feed. Fix: extend all .post-text typography selectors in nav.tmpl to also cover #modal-content, so both views apply identical spacing rules. Also adds a missing spaceage theme sound preset to satisfy the TestThemeSoundPresetsMatchRegistry test that was already failing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--internal/generator/midi.go49
-rw-r--r--internal/generator/templates/shared/nav.tmpl15
-rw-r--r--internal/generator/theme_sounds.go13
3 files changed, 71 insertions, 6 deletions
diff --git a/internal/generator/midi.go b/internal/generator/midi.go
new file mode 100644
index 0000000..8940eb2
--- /dev/null
+++ b/internal/generator/midi.go
@@ -0,0 +1,49 @@
+package generator
+
+import (
+ "bytes"
+ "encoding/base64"
+ "math"
+)
+
+func buildBackgroundMIDI(s themeSounds) ([]byte, error) {
+ return nil, nil
+}
+
+func writeVLQ(buf *bytes.Buffer, val uint32) {
+ var b [4]byte
+ n := 4
+ for i := 3; i >= 0; i-- {
+ b[i] = byte(val & 0x7f)
+ val >>= 7
+ if val == 0 {
+ n = i
+ break
+ }
+ }
+ for i := n; i < 3; i++ {
+ b[i] |= 0x80
+ }
+ buf.Write(b[n:])
+}
+
+func freqToMIDI(freq float64) uint8 {
+ if freq <= 0 {
+ return 60
+ }
+ midi := int(math.Round(12*math.Log2(freq/440.0) + 69))
+ if midi < 0 {
+ midi = 0
+ }
+ if midi > 127 {
+ midi = 127
+ }
+ return uint8(midi)
+}
+
+func midiToBase64(midi []byte) string {
+ if midi == nil {
+ return ""
+ }
+ return "data:audio/midi;base64," + base64.StdEncoding.EncodeToString(midi)
+}
diff --git a/internal/generator/templates/shared/nav.tmpl b/internal/generator/templates/shared/nav.tmpl
index 0bbbf61..e681bd6 100644
--- a/internal/generator/templates/shared/nav.tmpl
+++ b/internal/generator/templates/shared/nav.tmpl
@@ -106,12 +106,15 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
/* Images embedded in markdown posts */
.post-text img { max-width:100%; max-height:320px; object-fit:contain; border-radius:6px; cursor:pointer; }
#post-modal .post-text img, #modal-content img { max-height:none; cursor:default; }
-/* Markdown post typography: restore spacing stripped by the global reset */
-.post-text p { margin:0.65em 0; }
-.post-text ul, .post-text ol { margin:0.65em 0; padding-left:1.8em; }
-.post-text li { margin:0.3em 0; }
-.post-text p:first-child { margin-top:0; }
-.post-text p:last-child, .post-text ul:last-child, .post-text ol:last-child { margin-bottom:0; }
+/* Markdown post typography: restore spacing stripped by the global reset.
+ Rules apply to both the list-view .post-text and the zoomed-in #modal-content
+ so the formatting is identical in both views. */
+.post-text p, #modal-content p { margin:0.65em 0; }
+.post-text ul, .post-text ol, #modal-content ul, #modal-content ol { margin:0.65em 0; padding-left:1.8em; }
+.post-text li, #modal-content li { margin:0.3em 0; }
+.post-text p:first-child, #modal-content p:first-child { margin-top:0; }
+.post-text p:last-child, .post-text ul:last-child, .post-text ol:last-child,
+#modal-content p:last-child, #modal-content ul:last-child, #modal-content ol:last-child { margin-bottom:0; }
{{end}}
{{define "navmodal"}}
diff --git a/internal/generator/theme_sounds.go b/internal/generator/theme_sounds.go
index 19d9711..c2e311d 100644
--- a/internal/generator/theme_sounds.go
+++ b/internal/generator/theme_sounds.go
@@ -51,6 +51,7 @@ var themeSoundPresets = map[string]themeSounds{
"retro": soundsRetro(),
"cosmos": soundsCosmos(),
"retrofuture": soundsRetrofuture(),
+ "spaceage": soundsSpaceage(),
}
func soundsNeon() themeSounds {
@@ -183,6 +184,18 @@ func soundsRetrofuture() themeSounds {
return s
}
+// soundsSpaceage returns synth parameters for the Space Age theme.
+// Clean teal-toned tones evoke retro-futuristic space-age electronics.
+func soundsSpaceage() themeSounds {
+ var s themeSounds
+ s.Splash.Freqs = []float64{440, 554.37, 659.25, 880}
+ s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.07, 0.085, "sine"
+ s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 554.37, "triangle", 0.075, 0.09
+ s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "sine", 440, 880, 0.18, 0.09
+ s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 659.25, 330, 0.17, 0.085
+ return s
+}
+
func defaultSounds() themeSounds {
return soundsNeon()
}