Release v0.4.0: dev -> main #251

Merged
fen merged 138 commits from dev into main 2026-09-17 15:35:21 +00:00
3 changed files with 16 additions and 4 deletions
Showing only changes of commit 33ccfd373a - Show all commits
+1 -1
View File
@@ -16,7 +16,7 @@ func TestSecurityHeaders(t *testing.T) {
h := SecurityHeaders(pages) h := SecurityHeaders(pages)
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil)) h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil))
wantCSP := "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'" wantCSP := "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'"
if got := rec.Header().Get("Content-Security-Policy"); got != wantCSP { if got := rec.Header().Get("Content-Security-Policy"); got != wantCSP {
t.Errorf("CSP = %q, want %q", got, wantCSP) t.Errorf("CSP = %q, want %q", got, wantCSP)
} }
+14 -2
View File
@@ -4,6 +4,8 @@
--muted: #7A6A9E; --muted-fg: #C0B2DE; --fg: #F2EDF8; --muted: #7A6A9E; --muted-fg: #C0B2DE; --fg: #F2EDF8;
--accent: #C4A8F0; --border: #42355C; --accent: #C4A8F0; --border: #42355C;
--radius-lg: 20px; --radius: 10px; --radius-sm: 999px; --radius-lg: 20px; --radius: 10px; --radius-sm: 999px;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23C8C8D4' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: select chevron stroke (dark presets) */
--chevron-fg: #C8C8D4;
--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-mono: ui-monospace, "JetBrains Mono", "Fira Code", monospace; --font-mono: ui-monospace, "JetBrains Mono", "Fira Code", monospace;
} }
@@ -18,6 +20,8 @@
--accent: #7A7796; --border: #DAD7E6; --accent: #7A7796; --border: #DAD7E6;
--ok: #456F45; --warn: #7A5E1B; --err: #9E4054; --ok: #456F45; --warn: #7A5E1B; --err: #9E4054;
--on-accent: #F6F5FA; --on-accent: #F6F5FA;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23555560' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: light presets use a dark stroke */
--chevron-fg: #555560;
} }
[data-preset="pastel-lavender"] { [data-preset="pastel-lavender"] {
--bg: #e6e0f5; --surface: #f1edfa; --surface-2: #cbb8e7; --bg: #e6e0f5; --surface: #f1edfa; --surface-2: #cbb8e7;
@@ -25,6 +29,8 @@
--accent: #806bb8; --border: #c4b6e0; --accent: #806bb8; --border: #c4b6e0;
--ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054; --ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054;
--on-accent: #f1edfa; --on-accent: #f1edfa;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23555560' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: light presets use a dark stroke */
--chevron-fg: #555560;
} }
[data-preset="pastel-peach"] { [data-preset="pastel-peach"] {
--bg: #ffe0d6; --surface: #fff0ea; --surface-2: #ffc4a8; --bg: #ffe0d6; --surface: #fff0ea; --surface-2: #ffc4a8;
@@ -32,6 +38,8 @@
--accent: #f9826c; --border: #ffc9b5; --accent: #f9826c; --border: #ffc9b5;
--ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054; --ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054;
--on-accent: #4F2318; --on-accent: #4F2318;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23555560' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: light presets use a dark stroke */
--chevron-fg: #555560;
} }
[data-preset="pastel-cloud"] { [data-preset="pastel-cloud"] {
--bg: #fff0f6; --surface: #fff7fb; --surface-2: #ffc8dd; --bg: #fff0f6; --surface: #fff7fb; --surface-2: #ffc8dd;
@@ -39,6 +47,8 @@
--accent: #a2d2ff; --border: #ffccd9; --accent: #a2d2ff; --border: #ffccd9;
--ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054; --ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054;
--on-accent: #274a6b; --on-accent: #274a6b;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23555560' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: light presets use a dark stroke */
--chevron-fg: #555560;
} }
/* matching light/dark counterparts: same hue family, flipped lightness roles */ /* matching light/dark counterparts: same hue family, flipped lightness roles */
/* Midnight Light: light counterpart of midnight (violet family) */ /* Midnight Light: light counterpart of midnight (violet family) */
@@ -48,6 +58,8 @@
--accent: #7B5FC0; --border: #D8CEEC; --accent: #7B5FC0; --border: #D8CEEC;
--ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054; --ok: #3E6B3E; --warn: #7A5E1B; --err: #9E4054;
--on-accent: #FAF8FD; --on-accent: #FAF8FD;
--chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23555560' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); /* #136: light presets use a dark stroke */
--chevron-fg: #555560;
} }
/* Smooth Dark: dark counterpart of smooth (muted slate-violet family) */ /* Smooth Dark: dark counterpart of smooth (muted slate-violet family) */
[data-preset="smooth-dark"] { [data-preset="smooth-dark"] {
@@ -144,7 +156,7 @@ body {
border: none; outline: none; background: transparent; color: var(--fg); font: inherit; font-size: 23.2px; flex: 1; border: none; outline: none; background: transparent; color: var(--fg); font: inherit; font-size: 23.2px; flex: 1;
} }
.editor-head select { .editor-head select {
border: 1px solid var(--border); background: var(--surface-2); color: var(--muted-fg); border: 1px solid var(--border); background-color: var(--surface-2); color: var(--muted-fg);
border-radius: var(--radius); padding: 4px 10px; font: inherit; font-size: 21.6px; cursor: pointer; border-radius: var(--radius); padding: 4px 10px; font: inherit; font-size: 21.6px; cursor: pointer;
} }
/* shared code line metrics (#50): gutter + code must share one line box */ /* shared code line metrics (#50): gutter + code must share one line box */
@@ -602,7 +614,7 @@ select {
-webkit-appearance: none; -webkit-appearance: none;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
background: var(--bg) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 10px center; background: var(--bg) var(--chevron) no-repeat right 10px center; /* #136: themed chevron */
color: var(--fg); color: var(--fg);
font: inherit; font: inherit;
padding: 4px 30px 4px 12px; padding: 4px 30px 4px 12px;
+1 -1
View File
@@ -390,7 +390,7 @@ func SecurityHeaders(next http.Handler) http.Handler {
// is harmless and arguably desirable. // is harmless and arguably desirable.
h := w.Header() h := w.Header()
h.Set("Content-Security-Policy", h.Set("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'") "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'")
h.Set("Referrer-Policy", "no-referrer") h.Set("Referrer-Policy", "no-referrer")
h.Set("X-Content-Type-Options", "nosniff") h.Set("X-Content-Type-Options", "nosniff")
next.ServeHTTP(w, r) next.ServeHTTP(w, r)