修设置页主题色块被模板过滤器替换成 ZgotmplZ
html/template 对 style 属性做 CSS 过滤,linear-gradient(...) 未标记安全会被整体替换成
ZgotmplZ —— 线上设置页四个主题色块一直是灰底(既有问题,不是这次配色改动引入)。
- FuncMap 新增 safeCSS(string → template.CSS);值只来自 internal/theme.swatchOf,
由两个已校验的色值拼成,不接受用户输入,所以这里放开是安全的
- user/profile.html 的色块改 {{ safeCSS .Swatch }}
- 新增 TestThemeSwatchRenders:渲染 user/profile,断言不含 ZgotmplZ 且含渐变串;
已做变异验证(去掉 safeCSS 后该用例失败)
This commit is contained in:
@@ -496,3 +496,19 @@ shiroko `#4a7fc1`(3.69) → **`#3b6dac`**(4.74),sakura `#e5678f`(2.80) → **`
|
|||||||
`_scaffold.css` 令牌数 29 → 30。`StaticVersion` → **`20261021c`**。
|
`_scaffold.css` 令牌数 29 → 30。`StaticVersion` → **`20261021c`**。
|
||||||
最终审计 8 种组合(base 亮暗 + 三主题亮暗)全部 ≥4.5。⚠️ 写 CSS 用 python 改时注意:`git checkout` 会把
|
最终审计 8 种组合(base 亮暗 + 三主题亮暗)全部 ≥4.5。⚠️ 写 CSS 用 python 改时注意:`git checkout` 会把
|
||||||
base.css 还原成 CRLF,插入行要用同一行尾,否则变 MIXED。
|
base.css 还原成 CRLF,插入行要用同一行尾,否则变 MIXED。
|
||||||
|
|
||||||
|
## 18:5x 检查测试环境部署 → 抓到设置页色块 ZgotmplZ
|
||||||
|
|
||||||
|
**部署核对(都对)**:`base.css?v=20261021c`、三份 CSS(base/sakura/shiroko)与本地**逐字节一致**;
|
||||||
|
设置页主题列表 = 跟随站点默认 / 基础外观 / 樱花 / 砂狼白子,**test01 已消失**、名称无 `theme.name.*` key;
|
||||||
|
登录按钮是新蓝(#0e6fd0)白字,箱主页排版正常。
|
||||||
|
⚠️ **admin6 的主题被重置成「跟随站点默认」**(它原来选的是已删除的 test01)→ 箱主页 `<html>` 没有
|
||||||
|
`data-theme-style`,现在是基础外观。要验证主题得重新选 sakura/shiroko。
|
||||||
|
|
||||||
|
**P1 缺陷(既有,非本次改动引入)**:设置页四个主题色块全是 `style="background: ZgotmplZ"`。
|
||||||
|
`html/template` 会对 `style` 属性做 CSS 过滤,未标记安全的 `linear-gradient(...)` 一律替换成 ZgotmplZ。
|
||||||
|
`swatchOf` 一直在生成渐变串,所以这个色块**从来没显示过**。
|
||||||
|
修法:FuncMap 加 `safeCSS` → `template.CSS`,模板 `{{ safeCSS .Swatch }}`(值只来自 swatchOf,不接受用户输入)。
|
||||||
|
加了 `TestThemeSwatchRenders`(渲染 user/profile,断言不含 ZgotmplZ 且含渐变串),并做变异验证:
|
||||||
|
把 `safeCSS` 去掉 → 测试如期 FAIL。
|
||||||
|
⚠️ 教训:任何 `style="..."` 里塞模板值都要过一遍这个过滤器;模板名在测试里**不带 `.html`**(`user/profile`)。
|
||||||
|
|||||||
@@ -199,6 +199,13 @@ func FuncMap() []template.FuncMap {
|
|||||||
"themeName": func(lang, slug string) string {
|
"themeName": func(lang, slug string) string {
|
||||||
return theme.DisplayName(lang, slug)
|
return theme.DisplayName(lang, slug)
|
||||||
},
|
},
|
||||||
|
// safeCSS 把受控的 CSS 值标成安全,用于主题色块的 inline background。
|
||||||
|
// ⚠️ html/template 会过滤 style 属性里的值,linear-gradient(...) 直接被替换成
|
||||||
|
// ZgotmplZ —— 设置页每个主题的色块都会变成灰底(线上就是这样)。
|
||||||
|
// 值只来自 internal/theme.swatchOf(由两个已校验的色值拼成),不接受用户输入。
|
||||||
|
"safeCSS": func(s string) template.CSS {
|
||||||
|
return template.CSS(s)
|
||||||
|
},
|
||||||
|
|
||||||
// moderationStrictness 返回账号「最终生效」的审核严格度档位(lax / standard / strict)。
|
// moderationStrictness 返回账号「最终生效」的审核严格度档位(lax / standard / strict)。
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/tamakyi/TamaBox/internal/i18n"
|
"github.com/tamakyi/TamaBox/internal/i18n"
|
||||||
"github.com/tamakyi/TamaBox/internal/security/moderation"
|
"github.com/tamakyi/TamaBox/internal/security/moderation"
|
||||||
templatepkg "github.com/tamakyi/TamaBox/internal/template"
|
templatepkg "github.com/tamakyi/TamaBox/internal/template"
|
||||||
|
"github.com/tamakyi/TamaBox/internal/theme"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 审核严格度下拉框的解析:不依赖属性的书写顺序或是否存在额外属性
|
// 审核严格度下拉框的解析:不依赖属性的书写顺序或是否存在额外属性
|
||||||
@@ -423,3 +424,25 @@ func TestRenderUserQuestionList(t *testing.T) {
|
|||||||
t.Fatal("restriction banner should show expiry date")
|
t.Fatal("restriction banner should show expiry date")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestThemeSwatchRenders 主题色块走的是 inline style="background: <gradient>"。
|
||||||
|
// html/template 对 style 属性做 CSS 过滤,未标记安全的 linear-gradient(...) 会被换成
|
||||||
|
// ZgotmplZ —— 设置页每个主题的色块都变成灰底。这个用例钉住「色块真的渲染出来」。
|
||||||
|
func TestThemeSwatchRenders(t *testing.T) {
|
||||||
|
base := profileBaseData()
|
||||||
|
base["Themes"] = []theme.Theme{
|
||||||
|
{Slug: "sakura", Swatch: "linear-gradient(135deg, #fceef3 0 45%, #ba3e66 45% 100%)"},
|
||||||
|
}
|
||||||
|
base["CurrentTheme"] = "sakura"
|
||||||
|
|
||||||
|
out, err := renderToString(t, "user/profile", base)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("render: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(out, "ZgotmplZ") {
|
||||||
|
t.Fatal("色块被 html/template 过滤成 ZgotmplZ(检查是否漏了 safeCSS)")
|
||||||
|
}
|
||||||
|
if !strings.Contains(out, "linear-gradient(135deg, #fceef3 0 45%, #ba3e66 45% 100%)") {
|
||||||
|
t.Fatal("渲染结果里找不到主题色块的渐变")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -804,7 +804,7 @@
|
|||||||
{{ range .Themes }}
|
{{ range .Themes }}
|
||||||
<label class="tb-theme-opt">
|
<label class="tb-theme-opt">
|
||||||
<input class="uk-radio" type="radio" name="theme" value="{{ .Slug }}"{{ if eq $.CurrentTheme .Slug }} checked{{ end }}>
|
<input class="uk-radio" type="radio" name="theme" value="{{ .Slug }}"{{ if eq $.CurrentTheme .Slug }} checked{{ end }}>
|
||||||
<span class="tb-theme-swatch"{{ if .Swatch }} style="background: {{ .Swatch }}"{{ end }}></span>
|
<span class="tb-theme-swatch"{{ if .Swatch }} style="background: {{ safeCSS .Swatch }}"{{ end }}></span>
|
||||||
<span class="tb-theme-name">{{ themeName $.LangCode .Slug }}</span>
|
<span class="tb-theme-name">{{ themeName $.LangCode .Slug }}</span>
|
||||||
</label>
|
</label>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
Reference in New Issue
Block a user