theme v2
@@ -385,3 +385,24 @@ P1 剩余两项(首屏跟随系统深色、首页 Waline 懒加载)用户明
|
|||||||
3. `writePreview` 用全文搜 `data-theme="dark"` 判断是否已加属性 → 命中内联主题 css 里的选择器,深色预览没生效;
|
3. `writePreview` 用全文搜 `data-theme="dark"` 判断是否已加属性 → 命中内联主题 css 里的选择器,深色预览没生效;
|
||||||
改为只看 `<html ...>` 开标签。
|
改为只看 `<html ...>` 开标签。
|
||||||
4. 脚本改 form/user.go 时把插入块写在结构体中间,拼出 `} Language ...`;靠 Read 复查发现并重写。
|
4. 脚本改 form/user.go 时把插入块写在结构体中间,拼出 `} Language ...`;靠 Read 复查发现并重写。
|
||||||
|
|
||||||
|
## 主题 follow-up(部署后反馈两处)
|
||||||
|
|
||||||
|
1. **/user/* 不生效主题**:根因是 `ctx.Data["ThemeSlug"]` 只在 `question.Pager`(`/_/{domain}`)里注入,
|
||||||
|
`/user/*` 完全没走这条链路。修法:`internal/context/context.go` 的 Contexter 里按
|
||||||
|
`isThemeScope(path) && c.IsLogged` 注入 `theme.Resolve(c.User.Theme)`;
|
||||||
|
`isThemeScope` 只认 `/user` 与 `/user/`(不能用裸 `HasPrefix("/user")`,会误吞 `/username`)。
|
||||||
|
新增 `internal/context/context_test.go` 守住路径白名单;page.go 的注释同步改。
|
||||||
|
公开页(`/`、`/explore`、`/vote/{token}`)**仍不跟随**登录用户主题,保持站点默认。
|
||||||
|
|
||||||
|
2. **sakura 显示奇怪**(用户选择:顶栏白与粉底割裂 / 卡片纯白太突 / 底色分布不均):
|
||||||
|
- base.css 新增令牌 `--tb-navbar`(`:root` 里 `var(--tb-surface)`,亮暗两条 navbar 规则都改成
|
||||||
|
`var(--tb-navbar, var(--tb-surface))`),主题可单独给顶栏上色。
|
||||||
|
- sakura v2:底色改**纯色** `#fceef3`(不用渐变——渐变会被读成"不均匀"),
|
||||||
|
顶栏 `#fff6f9`、卡片 `#fffafc`(暖白,不再是纯白硬切),网点从 16px/0.14 放宽到 24px/0.05。
|
||||||
|
- 静态版本 `20261019f`;`_scaffold.css` 令牌说明 19→20。
|
||||||
|
- `profile.theme.hint` 四语言文案改成「提问箱页面 + 本人后台生效,公开页保持默认」。
|
||||||
|
- `zz_preview_test.go` 抽出 `inlineThemeCSS()`,并新增 `preview-profile-sakura-*`(后台页面也要在主题下检查)。
|
||||||
|
|
||||||
|
验证:`go build ./...`(须带 webp overlay)、i18n/theme/context/templates 四个包测试全绿。
|
||||||
|
渲染法:抓线上 `/_/admin6` HTML → 把 base.css 指到本地新文件、主题 css 内联 → 无头 Chrome `--headless=old` 截图。
|
||||||
|
|||||||
@@ -153,3 +153,17 @@
|
|||||||
`reports --domain|--email [--days]`(证据包)、`--pending`、`--stats --days N`(Top 被举报箱主 + Top 举报 IP);
|
`reports --domain|--email [--days]`(证据包)、`--pending`、`--stats --days N`(Top 被举报箱主 + Top 举报 IP);
|
||||||
`hide-public [--only-reported] [--since N]`。
|
`hide-public [--only-reported] [--since N]`。
|
||||||
- 本地冒烟:`NEKOBOX_CONFIG_PATH=<ini>`;`conf.Init` 强制 `app.external_url`、`server.salt`、`server.xsrf_key` 非空。
|
- 本地冒烟:`NEKOBOX_CONFIG_PATH=<ini>`;`conf.Init` 强制 `app.external_url`、`server.salt`、`server.xsrf_key` 非空。
|
||||||
|
|
||||||
|
## 主题(箱主个性化)
|
||||||
|
|
||||||
|
- 两个注入点,别再漏:`/_/{domain}/*` → `question.Pager` 按 `pageUser.Theme`;
|
||||||
|
`/user/*` → `internal/context` 的 Contexter 按 `c.User.Theme`(`isThemeScope()` 只认 `/user` 与 `/user/`)。
|
||||||
|
公开页(`/`、`/explore`、`/vote/{token}`)不跟随登录用户主题。
|
||||||
|
- 主题 = 一个 css 文件只覆盖令牌;新增主题不用改 Go/模板,放 `static/css/themes/<slug>.css` +
|
||||||
|
`[theme] available` 登记即可(`static/fs.go` 已嵌整个目录)。底稿 `_scaffold.css`。
|
||||||
|
- **必须同时写浅色块与深色块**(`html[data-theme-style=x]` / `html[data-theme="dark"][data-theme-style=x]`),
|
||||||
|
`TestThemeCSSComplete` 会查;色块预览由浅色块的 `--tb-bg` + `--tb-primary` 自动生成(色值过正则防注入)。
|
||||||
|
- 令牌 `--tb-navbar`:顶栏底色,默认 `var(--tb-surface)`。页面底色偏彩时主题应覆盖它,
|
||||||
|
否则顶栏是纯白带、压在彩底上割裂(用户实测反馈过)。
|
||||||
|
- 主题底色用**纯色**,别用整页渐变——会被读成「底色分布不均匀」;图案建议 ≥24px、透明度 ≤0.06。
|
||||||
|
- 改了 base.css / 主题 css 必须 +1 `conf.StaticVersion`(两者共用同一个 v)。
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ var (
|
|||||||
BuildCommit = "dev"
|
BuildCommit = "dev"
|
||||||
|
|
||||||
// StaticVersion 静态资源缓存版本号:base.css 与主题 css 共用,改样式只改这一处。
|
// StaticVersion 静态资源缓存版本号:base.css 与主题 css 共用,改样式只改这一处。
|
||||||
StaticVersion = "20261019e"
|
StaticVersion = "20261019f"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 文本审核通道取值([security] text_censor_source)。定义在 conf 侧,
|
// 文本审核通道取值([security] text_censor_source)。定义在 conf 侧,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/tamakyi/TamaBox/internal/i18n"
|
"github.com/tamakyi/TamaBox/internal/i18n"
|
||||||
"github.com/tamakyi/TamaBox/internal/shared"
|
"github.com/tamakyi/TamaBox/internal/shared"
|
||||||
templatepkg "github.com/tamakyi/TamaBox/internal/template"
|
templatepkg "github.com/tamakyi/TamaBox/internal/template"
|
||||||
|
"github.com/tamakyi/TamaBox/internal/theme"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EndpointType string
|
type EndpointType string
|
||||||
@@ -239,6 +240,13 @@ func Contexter() flamego.Handler {
|
|||||||
isUserPage := strings.HasPrefix(path, "/user") || strings.HasPrefix(path, "/_/")
|
isUserPage := strings.HasPrefix(path, "/user") || strings.HasPrefix(path, "/_/")
|
||||||
c.Data["IsUserPage"] = isUserPage
|
c.Data["IsUserPage"] = isUserPage
|
||||||
|
|
||||||
|
// 主题:/user 后台是箱主本人的页面,跟随本人配置;
|
||||||
|
// /_/{domain} 的箱主主题由 question.Pager 覆盖(访客看到的是箱主的选择)。
|
||||||
|
// 空串(未选且站点无默认主题)= 不加载主题 css。
|
||||||
|
if isThemeScope(path) && c.IsLogged {
|
||||||
|
c.Data["ThemeSlug"] = theme.Resolve(c.User.Theme)
|
||||||
|
}
|
||||||
|
|
||||||
// SEO:仅公开页(首页/注册/登录/explore)允许被搜索引擎收录;
|
// SEO:仅公开页(首页/注册/登录/explore)允许被搜索引擎收录;
|
||||||
// 提问内容(提问箱页、单题页)、密码页、私信、用户后台等隐私页一律 noindex。
|
// 提问内容(提问箱页、单题页)、密码页、私信、用户后台等隐私页一律 noindex。
|
||||||
isPublicPage := path == "/" || path == "/register" || path == "/login" || strings.HasPrefix(path, "/explore")
|
isPublicPage := path == "/" || path == "/register" || path == "/login" || strings.HasPrefix(path, "/explore")
|
||||||
@@ -327,3 +335,10 @@ func (c *Context) Lang() string {
|
|||||||
}
|
}
|
||||||
return i18n.Default
|
return i18n.Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isThemeScope 判断该路径的主题是否由「当前登录用户自己的配置」决定。
|
||||||
|
// 只覆盖 /user 后台(本人页面);提问箱相关页面由 question.Pager 按箱主注入,
|
||||||
|
// 公开页(首页/探索/登录)保持站点默认外观,不跟随登录状态变化。
|
||||||
|
func isThemeScope(path string) bool {
|
||||||
|
return path == "/user" || strings.HasPrefix(path, "/user/")
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
// 主题作用域:/user 后台必须命中(否则设置页、题目管理页拿不到自己的主题),
|
||||||
|
// 其余路径不得命中(提问箱页面由 question.Pager 按箱主注入,公开页保持站点默认)。
|
||||||
|
func TestIsThemeScope(t *testing.T) {
|
||||||
|
cases := map[string]bool{
|
||||||
|
"/user": true,
|
||||||
|
"/user/": true,
|
||||||
|
"/user/profile": true,
|
||||||
|
"/user/questions": true,
|
||||||
|
"/user/votes/1/results": true,
|
||||||
|
"/username": false, // 前缀相近但不是用户后台
|
||||||
|
"/_/admin6": false,
|
||||||
|
"/_/admin6/share-card": false,
|
||||||
|
"/": false,
|
||||||
|
"/explore": false,
|
||||||
|
"/vote/abc": false,
|
||||||
|
"/api/v1/user/admin6": false,
|
||||||
|
"/api/v1/user": false,
|
||||||
|
"/deactivated": false,
|
||||||
|
}
|
||||||
|
|
||||||
|
for path, want := range cases {
|
||||||
|
if got := isThemeScope(path); got != want {
|
||||||
|
t.Errorf("isThemeScope(%q) = %v, want %v", path, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -933,7 +933,7 @@ var enDict = map[string]string{
|
|||||||
|
|
||||||
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
||||||
"profile.theme.title": "Theme",
|
"profile.theme.title": "Theme",
|
||||||
"profile.theme.hint": "Applies to your question box pages only; the rest of the site keeps the default look.",
|
"profile.theme.hint": "Applies to your question box pages and your dashboard; public pages (home, explore) keep the default look.",
|
||||||
"profile.theme.followDefault": "Follow site default",
|
"profile.theme.followDefault": "Follow site default",
|
||||||
"profile.theme.save": "Save theme",
|
"profile.theme.save": "Save theme",
|
||||||
"profile.theme.saved": "Theme saved",
|
"profile.theme.saved": "Theme saved",
|
||||||
|
|||||||
@@ -933,7 +933,7 @@ var jaDict = map[string]string{
|
|||||||
|
|
||||||
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
||||||
"profile.theme.title": "テーマ",
|
"profile.theme.title": "テーマ",
|
||||||
"profile.theme.hint": "質問箱のページにのみ適用されます。他のページは既定の外観のままです。",
|
"profile.theme.hint": "質問箱のページと管理画面に適用されます。ホーム・探索などの公開ページは既定の外観のままです。",
|
||||||
"profile.theme.followDefault": "サイト既定に従う",
|
"profile.theme.followDefault": "サイト既定に従う",
|
||||||
"profile.theme.save": "テーマを保存",
|
"profile.theme.save": "テーマを保存",
|
||||||
"profile.theme.saved": "テーマを保存しました",
|
"profile.theme.saved": "テーマを保存しました",
|
||||||
|
|||||||
@@ -874,7 +874,7 @@ var zhCNDict = map[string]string{
|
|||||||
|
|
||||||
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
||||||
"profile.theme.title": "主题外观",
|
"profile.theme.title": "主题外观",
|
||||||
"profile.theme.hint": "仅对提问箱页面生效,站内其它页面保持默认外观。",
|
"profile.theme.hint": "对提问箱页面和你的后台页面生效,首页/探索等公开页保持默认外观。",
|
||||||
"profile.theme.followDefault": "跟随站点默认",
|
"profile.theme.followDefault": "跟随站点默认",
|
||||||
"profile.theme.save": "保存主题",
|
"profile.theme.save": "保存主题",
|
||||||
"profile.theme.saved": "主题已保存",
|
"profile.theme.saved": "主题已保存",
|
||||||
|
|||||||
@@ -933,7 +933,7 @@ var zhTWDict = map[string]string{
|
|||||||
|
|
||||||
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
// 主题:设置页选择器与主题显示名(theme.name.<slug> 由 internal/theme 约定)
|
||||||
"profile.theme.title": "主題外觀",
|
"profile.theme.title": "主題外觀",
|
||||||
"profile.theme.hint": "僅對提問箱頁面生效,站內其他頁面維持預設外觀。",
|
"profile.theme.hint": "對提問箱頁面與你的後台頁面生效,首頁/探索等公開頁維持預設外觀。",
|
||||||
"profile.theme.followDefault": "跟隨站點預設",
|
"profile.theme.followDefault": "跟隨站點預設",
|
||||||
"profile.theme.save": "儲存主題",
|
"profile.theme.save": "儲存主題",
|
||||||
"profile.theme.saved": "主題已儲存",
|
"profile.theme.saved": "主題已儲存",
|
||||||
|
|||||||
|
After Width: | Height: | Size: 251 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 257 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 308 KiB |
@@ -11,6 +11,8 @@
|
|||||||
--tb-surface: #ffffff;
|
--tb-surface: #ffffff;
|
||||||
--tb-surface-2: #f4f6f8;
|
--tb-surface-2: #f4f6f8;
|
||||||
--tb-surface-hover: #f3f7ff;
|
--tb-surface-hover: #f3f7ff;
|
||||||
|
/* 顶栏底色:默认跟随卡片面;主题想消除「纯白顶栏压在彩色底上」的割裂时单独覆盖 */
|
||||||
|
--tb-navbar: var(--tb-surface);
|
||||||
--tb-border: #e8eaee;
|
--tb-border: #e8eaee;
|
||||||
--tb-text: #1f2329;
|
--tb-text: #1f2329;
|
||||||
--tb-text-secondary: #5c6370;
|
--tb-text-secondary: #5c6370;
|
||||||
@@ -23,6 +25,10 @@
|
|||||||
--tb-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 28px -18px rgba(16, 24, 40, 0.20);
|
--tb-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 28px -18px rgba(16, 24, 40, 0.20);
|
||||||
--tb-shadow-hover: 0 1px 2px rgba(16, 24, 40, 0.05), 0 18px 40px -20px rgba(16, 24, 40, 0.28);
|
--tb-shadow-hover: 0 1px 2px rgba(16, 24, 40, 0.05), 0 18px 40px -20px rgba(16, 24, 40, 0.28);
|
||||||
--tb-font: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
|
--tb-font: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
|
||||||
|
/* 整页背景:主题可覆盖。图案层叠在背景图之上,两者都不用时保持纯色底。 */
|
||||||
|
--tb-page-image: none;
|
||||||
|
--tb-page-pattern: none;
|
||||||
|
--tb-page-pattern-size: auto;
|
||||||
}
|
}
|
||||||
html[data-theme="dark"] {
|
html[data-theme="dark"] {
|
||||||
--tb-bg: #1a1d23;
|
--tb-bg: #1a1d23;
|
||||||
@@ -134,7 +140,7 @@
|
|||||||
color: var(--tb-text) !important;
|
color: var(--tb-text) !important;
|
||||||
}
|
}
|
||||||
html[data-theme="dark"] .uk-navbar-container {
|
html[data-theme="dark"] .uk-navbar-container {
|
||||||
background-color: var(--tb-surface) !important;
|
background-color: var(--tb-navbar, var(--tb-surface)) !important;
|
||||||
color: var(--tb-text) !important;
|
color: var(--tb-text) !important;
|
||||||
}
|
}
|
||||||
html[data-theme="dark"] .uk-navbar-nav > li > a,
|
html[data-theme="dark"] .uk-navbar-nav > li > a,
|
||||||
@@ -239,12 +245,19 @@
|
|||||||
html[data-theme="dark"] .explore-intro {
|
html[data-theme="dark"] .explore-intro {
|
||||||
color: var(--tb-text-muted) !important;
|
color: var(--tb-text-muted) !important;
|
||||||
}
|
}
|
||||||
/* 切换按钮图标切换 */
|
/* 切换按钮图标切换(内联 SVG,不依赖 UIkit 图标库) */
|
||||||
|
#theme-toggle .tb-icon-light, #theme-toggle-mobile .tb-icon-light,
|
||||||
|
#theme-toggle .tb-icon-dark, #theme-toggle-mobile .tb-icon-dark {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#theme-toggle .tb-icon-light svg, #theme-toggle-mobile .tb-icon-light svg,
|
||||||
|
#theme-toggle .tb-icon-dark svg, #theme-toggle-mobile .tb-icon-dark svg { display: block; }
|
||||||
#theme-toggle .tb-icon-dark, #theme-toggle-mobile .tb-icon-dark { display: none; }
|
#theme-toggle .tb-icon-dark, #theme-toggle-mobile .tb-icon-dark { display: none; }
|
||||||
html[data-theme="dark"] #theme-toggle .tb-icon-light,
|
html[data-theme="dark"] #theme-toggle .tb-icon-light,
|
||||||
html[data-theme="dark"] #theme-toggle-mobile .tb-icon-light { display: none; }
|
html[data-theme="dark"] #theme-toggle-mobile .tb-icon-light { display: none; }
|
||||||
html[data-theme="dark"] #theme-toggle .tb-icon-dark,
|
html[data-theme="dark"] #theme-toggle .tb-icon-dark,
|
||||||
html[data-theme="dark"] #theme-toggle-mobile .tb-icon-dark { display: inline; }
|
html[data-theme="dark"] #theme-toggle-mobile .tb-icon-dark { display: inline-flex; }
|
||||||
|
|
||||||
/* 基础质感层:只调整外观(圆角/投影/字体/数字对齐),不改任何结构与布局。
|
/* 基础质感层:只调整外观(圆角/投影/字体/数字对齐),不改任何结构与布局。
|
||||||
颜色一律取自头部令牌,亮暗两套自动生效,因此这里不需要再写 html[data-theme="dark"] 分支。 */
|
颜色一律取自头部令牌,亮暗两套自动生效,因此这里不需要再写 html[data-theme="dark"] 分支。 */
|
||||||
@@ -253,6 +266,12 @@
|
|||||||
body {
|
body {
|
||||||
font-family: var(--tb-font);
|
font-family: var(--tb-font);
|
||||||
background-color: var(--tb-bg);
|
background-color: var(--tb-bg);
|
||||||
|
/* 主题的整页背景:图案(平铺)在上,图片(cover)在下,都不设置时等价于纯色 */
|
||||||
|
background-image: var(--tb-page-pattern, none), var(--tb-page-image, none);
|
||||||
|
background-size: var(--tb-page-pattern-size, auto), cover;
|
||||||
|
background-repeat: repeat, no-repeat;
|
||||||
|
background-position: left top, center center;
|
||||||
|
background-attachment: scroll, fixed;
|
||||||
color: var(--tb-text);
|
color: var(--tb-text);
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
@@ -306,7 +325,7 @@
|
|||||||
box-shadow: var(--tb-shadow);
|
box-shadow: var(--tb-shadow);
|
||||||
}
|
}
|
||||||
.uk-navbar-container:not(.uk-navbar-transparent) {
|
.uk-navbar-container:not(.uk-navbar-transparent) {
|
||||||
background-color: var(--tb-surface);
|
background-color: var(--tb-navbar, var(--tb-surface));
|
||||||
}
|
}
|
||||||
/* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */
|
/* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */
|
||||||
.uk-button:focus-visible,
|
.uk-button:focus-visible,
|
||||||
@@ -320,6 +339,89 @@
|
|||||||
color: var(--tb-text-muted);
|
color: var(--tb-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 主题选择器(设置页):色块 + 名称。纯展示,不参与主题令牌,所以放在基础层。 */
|
||||||
|
.tb-theme-hint {
|
||||||
|
margin: 0 0 6px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--tb-text-muted);
|
||||||
|
}
|
||||||
|
.tb-theme-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
margin: 8px 0 2px;
|
||||||
|
}
|
||||||
|
.tb-theme-opt {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 7px 9px;
|
||||||
|
border: 1px solid var(--tb-border);
|
||||||
|
border-radius: var(--tb-radius-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.tb-theme-opt:hover {
|
||||||
|
background-color: var(--tb-surface-hover);
|
||||||
|
}
|
||||||
|
.tb-theme-opt input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.tb-theme-swatch {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: var(--tb-radius-xs);
|
||||||
|
border: 1px solid var(--tb-border);
|
||||||
|
background-color: var(--tb-surface-2);
|
||||||
|
}
|
||||||
|
/* 选中态用描边而不是 :has(),兼容老 WebView */
|
||||||
|
.tb-theme-opt input:checked + .tb-theme-swatch {
|
||||||
|
outline: 2px solid var(--tb-primary);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
.tb-theme-name {
|
||||||
|
font-size: 0.84rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.tb-theme-opt input:checked ~ .tb-theme-name {
|
||||||
|
color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UIkit 组件跟随主题色:UIkit 3.3.3 的主色是编译期常量(#1e87f0),
|
||||||
|
CSS 变量注入不进去,只能按组件覆盖。基础主题的 --tb-primary 恰好就是 #1e87f0,
|
||||||
|
所以这段对默认外观零改动,只是让箱主主题能贯穿到按钮/链接/勾选。 */
|
||||||
|
a, .uk-link {
|
||||||
|
color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
a:hover, .uk-link:hover {
|
||||||
|
color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
.uk-button-primary {
|
||||||
|
background-color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
.uk-button-primary:hover,
|
||||||
|
.uk-button-primary:focus {
|
||||||
|
background-color: var(--tb-primary);
|
||||||
|
filter: brightness(1.07);
|
||||||
|
}
|
||||||
|
.uk-checkbox:checked,
|
||||||
|
.uk-checkbox:indeterminate,
|
||||||
|
.uk-radio:checked {
|
||||||
|
background-color: var(--tb-primary);
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
.uk-input:focus,
|
||||||
|
.uk-select:focus,
|
||||||
|
.uk-textarea:focus {
|
||||||
|
border-color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
.uk-tab > .uk-active > a {
|
||||||
|
border-color: var(--tb-primary);
|
||||||
|
}
|
||||||
|
.uk-text-primary {
|
||||||
|
color: var(--tb-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 轻量胶囊:用于投票类型、热门标签等「只是分类信息」的位置。
|
/* 轻量胶囊:用于投票类型、热门标签等「只是分类信息」的位置。
|
||||||
实心 uk-label 一屏多个会变成一排色块,这里统一降级为浅底 + 次要色文字。 */
|
实心 uk-label 一屏多个会变成一排色块,这里统一降级为浅底 + 次要色文字。 */
|
||||||
.tb-chip {
|
.tb-chip {
|
||||||
@@ -609,11 +711,13 @@ a.tb-chip:hover {
|
|||||||
border-radius: var(--tb-radius-xs);
|
border-radius: var(--tb-radius-xs);
|
||||||
}
|
}
|
||||||
.uk-progress::-webkit-progress-value {
|
.uk-progress::-webkit-progress-value {
|
||||||
|
/* 两端都圆:值 100% 时若只圆左边,右端方角会顶出轨道圆角 */
|
||||||
background-color: var(--tb-primary);
|
background-color: var(--tb-primary);
|
||||||
border-radius: var(--tb-radius-xs) 0 0 var(--tb-radius-xs);
|
border-radius: var(--tb-radius-xs);
|
||||||
}
|
}
|
||||||
.uk-progress::-moz-progress-bar {
|
.uk-progress::-moz-progress-bar {
|
||||||
background-color: var(--tb-primary);
|
background-color: var(--tb-primary);
|
||||||
|
border-radius: var(--tb-radius-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移动端底部操作栏:固定底栏承载语言切换与深色模式,桌面端隐藏 */
|
/* 移动端底部操作栏:固定底栏承载语言切换与深色模式,桌面端隐藏 */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · </title>
|
<title>预览 16:08 · </title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
@@ -636,7 +636,7 @@ document.getElementById("introcolor").style.color = "#ffffff";
|
|||||||
href="/_/tester/1">查看回答</a>
|
href="/_/tester/1">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
||||||
2026-10-19 15:15:39
|
2026-10-19 16:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
||||||
</p>
|
</p>
|
||||||
@@ -648,7 +648,7 @@ document.getElementById("introcolor").style.color = "#ffffff";
|
|||||||
href="/_/tester/2">查看回答</a>
|
href="/_/tester/2">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
|
|
||||||
2026-10-19 14:15:39
|
2026-10-19 15:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · </title>
|
<title>预览 16:08 · </title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
@@ -636,7 +636,7 @@ document.getElementById("introcolor").style.color = "#ffffff";
|
|||||||
href="/_/tester/1">查看回答</a>
|
href="/_/tester/1">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
||||||
2026-10-19 15:15:39
|
2026-10-19 16:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
||||||
</p>
|
</p>
|
||||||
@@ -648,7 +648,7 @@ document.getElementById("introcolor").style.color = "#ffffff";
|
|||||||
href="/_/tester/2">查看回答</a>
|
href="/_/tester/2">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
|
|
||||||
2026-10-19 14:15:39
|
2026-10-19 15:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · 投票</title>
|
<title>预览 16:08 · 投票</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · 投票</title>
|
<title>预览 16:08 · 投票</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · TamaBox</title>
|
<title>预览 16:08 · TamaBox</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · TamaBox</title>
|
<title>预览 16:08 · TamaBox</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · 设置</title>
|
<title>预览 16:08 · 设置</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · 设置</title>
|
<title>预览 16:08 · 设置</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · 设置</title>
|
<title>预览 16:08 · 设置</title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · </title>
|
<title>预览 16:08 · </title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
@@ -22,13 +22,17 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/base.css?v="/>
|
<link rel="stylesheet" href="/static/css/base.css?v="/>
|
||||||
|
|
||||||
<style>/* 樱花(sakura):粉调 + 细网点图案,纯 CSS 实现,不依赖图片素材。
|
<style>/* 樱花(sakura):粉调 + 极淡网点,纯 CSS 实现,不依赖图片素材。
|
||||||
复制 _scaffold.css 写的示例:只覆盖令牌,未改动任何布局。 */
|
只覆盖令牌,不改动任何布局。要点:
|
||||||
|
- 页面底色用纯色(不用渐变),保证整页色感一致;
|
||||||
|
- 顶栏与卡片都是「带粉调的暖白」而不是纯白,和粉底之间是过渡不是硬切;
|
||||||
|
- 网点放大到 24px、透明度降到 0.05,只作纸纹,不在留白处抢注意力。 */
|
||||||
html[data-theme-style="sakura"] {
|
html[data-theme-style="sakura"] {
|
||||||
--tb-bg: #fff6f8;
|
--tb-bg: #fceef3;
|
||||||
--tb-surface: #ffffff;
|
--tb-surface: #fffafc;
|
||||||
--tb-surface-2: #fdeef2;
|
--tb-surface-2: #fbe8ee;
|
||||||
--tb-surface-hover: #fdf1f5;
|
--tb-surface-hover: #fdf1f5;
|
||||||
|
--tb-navbar: #fff6f9;
|
||||||
--tb-border: #f2dde4;
|
--tb-border: #f2dde4;
|
||||||
|
|
||||||
--tb-text: #3a2b30;
|
--tb-text: #3a2b30;
|
||||||
@@ -42,16 +46,17 @@ html[data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.14) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme="dark"][data-theme-style="sakura"] {
|
html[data-theme="dark"][data-theme-style="sakura"] {
|
||||||
--tb-bg: #241a1f;
|
--tb-bg: #241a1f;
|
||||||
--tb-surface: #2e2129;
|
--tb-surface: #2f2228;
|
||||||
--tb-surface-2: #3a2a33;
|
--tb-surface-2: #3a2a33;
|
||||||
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
||||||
--tb-border: #49333d;
|
--tb-navbar: #2a1e24;
|
||||||
|
--tb-border: #4a333e;
|
||||||
|
|
||||||
--tb-text: #f2e4e9;
|
--tb-text: #f2e4e9;
|
||||||
--tb-text-secondary: #c6aab4;
|
--tb-text-secondary: #c6aab4;
|
||||||
@@ -64,8 +69,8 @@ html[data-theme="dark"][data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.10) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -682,7 +687,7 @@ document.getElementById("introcolor").style.color = "#6b545c";
|
|||||||
href="/_/tester/1">查看回答</a>
|
href="/_/tester/1">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
||||||
2026-10-19 15:15:39
|
2026-10-19 16:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
||||||
</p>
|
</p>
|
||||||
@@ -694,7 +699,7 @@ document.getElementById("introcolor").style.color = "#6b545c";
|
|||||||
href="/_/tester/2">查看回答</a>
|
href="/_/tester/2">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
|
|
||||||
2026-10-19 14:15:39
|
2026-10-19 15:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>预览 15:15 · </title>
|
<title>预览 16:08 · </title>
|
||||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||||
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
<meta name="description" content="狼的提问箱——一个无需注册、可匿名提问的匿名提问箱,安全地倾诉与回应。">
|
||||||
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
<meta name="keywords" content="匿名提问箱,提问箱,匿名提问,狼的提问箱,匿名问答,匿名提问网站">
|
||||||
@@ -22,13 +22,17 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/base.css?v="/>
|
<link rel="stylesheet" href="/static/css/base.css?v="/>
|
||||||
|
|
||||||
<style>/* 樱花(sakura):粉调 + 细网点图案,纯 CSS 实现,不依赖图片素材。
|
<style>/* 樱花(sakura):粉调 + 极淡网点,纯 CSS 实现,不依赖图片素材。
|
||||||
复制 _scaffold.css 写的示例:只覆盖令牌,未改动任何布局。 */
|
只覆盖令牌,不改动任何布局。要点:
|
||||||
|
- 页面底色用纯色(不用渐变),保证整页色感一致;
|
||||||
|
- 顶栏与卡片都是「带粉调的暖白」而不是纯白,和粉底之间是过渡不是硬切;
|
||||||
|
- 网点放大到 24px、透明度降到 0.05,只作纸纹,不在留白处抢注意力。 */
|
||||||
html[data-theme-style="sakura"] {
|
html[data-theme-style="sakura"] {
|
||||||
--tb-bg: #fff6f8;
|
--tb-bg: #fceef3;
|
||||||
--tb-surface: #ffffff;
|
--tb-surface: #fffafc;
|
||||||
--tb-surface-2: #fdeef2;
|
--tb-surface-2: #fbe8ee;
|
||||||
--tb-surface-hover: #fdf1f5;
|
--tb-surface-hover: #fdf1f5;
|
||||||
|
--tb-navbar: #fff6f9;
|
||||||
--tb-border: #f2dde4;
|
--tb-border: #f2dde4;
|
||||||
|
|
||||||
--tb-text: #3a2b30;
|
--tb-text: #3a2b30;
|
||||||
@@ -42,16 +46,17 @@ html[data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.14) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme="dark"][data-theme-style="sakura"] {
|
html[data-theme="dark"][data-theme-style="sakura"] {
|
||||||
--tb-bg: #241a1f;
|
--tb-bg: #241a1f;
|
||||||
--tb-surface: #2e2129;
|
--tb-surface: #2f2228;
|
||||||
--tb-surface-2: #3a2a33;
|
--tb-surface-2: #3a2a33;
|
||||||
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
||||||
--tb-border: #49333d;
|
--tb-navbar: #2a1e24;
|
||||||
|
--tb-border: #4a333e;
|
||||||
|
|
||||||
--tb-text: #f2e4e9;
|
--tb-text: #f2e4e9;
|
||||||
--tb-text-secondary: #c6aab4;
|
--tb-text-secondary: #c6aab4;
|
||||||
@@ -64,8 +69,8 @@ html[data-theme="dark"][data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.10) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -682,7 +687,7 @@ document.getElementById("introcolor").style.color = "#6b545c";
|
|||||||
href="/_/tester/1">查看回答</a>
|
href="/_/tester/1">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
<span class="tb-pin-flag" title="已置顶">⭐</span>
|
||||||
2026-10-19 15:15:39
|
2026-10-19 16:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">置顶的问题
|
||||||
</p>
|
</p>
|
||||||
@@ -694,7 +699,7 @@ document.getElementById("introcolor").style.color = "#6b545c";
|
|||||||
href="/_/tester/2">查看回答</a>
|
href="/_/tester/2">查看回答</a>
|
||||||
<div class="uk-text-left uk-text-small uk-text-muted">
|
<div class="uk-text-left uk-text-small uk-text-muted">
|
||||||
|
|
||||||
2026-10-19 14:15:39
|
2026-10-19 15:08:02
|
||||||
</div>
|
</div>
|
||||||
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
<p class="uk-text-small uk-text-break tb-preline tb-clamp-5">普通问题
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 251 KiB |
|
After Width: | Height: | Size: 306 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 39 KiB |
@@ -78,7 +78,7 @@ func Pager(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 主题只作用于箱主相关页面(提问箱主页 / 单题页 / 密码页 / 分享卡路由),
|
// 主题只作用于箱主相关页面(提问箱主页 / 单题页 / 密码页 / 分享卡路由),
|
||||||
// 与背景图、颜色同属箱主个性化配置;/user 后台保持中性外观。
|
// 与背景图、颜色同属箱主个性化配置;/user 后台由 Contexter 按登录用户自己的配置注入。
|
||||||
// 空串 = 不加载主题 css(站点默认就是基础外观时省掉一次请求)。
|
// 空串 = 不加载主题 css(站点默认就是基础外观时省掉一次请求)。
|
||||||
ctx.Data["ThemeSlug"] = theme.Resolve(pageUser.Theme)
|
ctx.Data["ThemeSlug"] = theme.Resolve(pageUser.Theme)
|
||||||
// 页面密码检查
|
// 页面密码检查
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
--tb-surface: #ffffff;
|
--tb-surface: #ffffff;
|
||||||
--tb-surface-2: #f4f6f8;
|
--tb-surface-2: #f4f6f8;
|
||||||
--tb-surface-hover: #f3f7ff;
|
--tb-surface-hover: #f3f7ff;
|
||||||
|
/* 顶栏底色:默认跟随卡片面;主题想消除「纯白顶栏压在彩色底上」的割裂时单独覆盖 */
|
||||||
|
--tb-navbar: var(--tb-surface);
|
||||||
--tb-border: #e8eaee;
|
--tb-border: #e8eaee;
|
||||||
--tb-text: #1f2329;
|
--tb-text: #1f2329;
|
||||||
--tb-text-secondary: #5c6370;
|
--tb-text-secondary: #5c6370;
|
||||||
@@ -138,7 +140,7 @@
|
|||||||
color: var(--tb-text) !important;
|
color: var(--tb-text) !important;
|
||||||
}
|
}
|
||||||
html[data-theme="dark"] .uk-navbar-container {
|
html[data-theme="dark"] .uk-navbar-container {
|
||||||
background-color: var(--tb-surface) !important;
|
background-color: var(--tb-navbar, var(--tb-surface)) !important;
|
||||||
color: var(--tb-text) !important;
|
color: var(--tb-text) !important;
|
||||||
}
|
}
|
||||||
html[data-theme="dark"] .uk-navbar-nav > li > a,
|
html[data-theme="dark"] .uk-navbar-nav > li > a,
|
||||||
@@ -323,7 +325,7 @@
|
|||||||
box-shadow: var(--tb-shadow);
|
box-shadow: var(--tb-shadow);
|
||||||
}
|
}
|
||||||
.uk-navbar-container:not(.uk-navbar-transparent) {
|
.uk-navbar-container:not(.uk-navbar-transparent) {
|
||||||
background-color: var(--tb-surface);
|
background-color: var(--tb-navbar, var(--tb-surface));
|
||||||
}
|
}
|
||||||
/* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */
|
/* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */
|
||||||
.uk-button:focus-visible,
|
.uk-button:focus-visible,
|
||||||
|
|||||||
@@ -15,11 +15,13 @@
|
|||||||
display / flex / grid、position 一律不动 —— 主题不是换皮模板。
|
display / flex / grid、position 一律不动 —— 主题不是换皮模板。
|
||||||
3. 本文件不参与构建,仅作参考;真正生效的是同目录下的 <slug>.css。
|
3. 本文件不参与构建,仅作参考;真正生效的是同目录下的 <slug>.css。
|
||||||
|
|
||||||
── 可用的 19 个令牌 ──────────────────────────────────────────────
|
── 可用的 20 个令牌 ──────────────────────────────────────────────
|
||||||
底色层 --tb-bg 页面底色(html/body)
|
底色层 --tb-bg 页面底色(html/body)
|
||||||
--tb-surface 卡片、输入框等前景面板
|
--tb-surface 卡片、输入框等前景面板
|
||||||
--tb-surface-2 次级面(标签底、进度条轨道、代码块)
|
--tb-surface-2 次级面(标签底、进度条轨道、代码块)
|
||||||
--tb-surface-hover 悬停底(列表行、下拉项)
|
--tb-surface-hover 悬停底(列表行、下拉项)
|
||||||
|
--tb-navbar 顶栏底色(不写则同 --tb-surface;
|
||||||
|
页面底色不是白时建议覆盖成 bg 或它的同色,否则顶栏会成为一条白带)
|
||||||
线条 --tb-border 边框、分隔线
|
线条 --tb-border 边框、分隔线
|
||||||
文字 --tb-text 正文
|
文字 --tb-text 正文
|
||||||
--tb-text-secondary 次要文字(说明、meta)
|
--tb-text-secondary 次要文字(说明、meta)
|
||||||
@@ -50,6 +52,7 @@ html[data-theme-style="SLUG"] {
|
|||||||
--tb-surface: #ffffff;
|
--tb-surface: #ffffff;
|
||||||
--tb-surface-2: #f4f6f8;
|
--tb-surface-2: #f4f6f8;
|
||||||
--tb-surface-hover: #f3f7ff;
|
--tb-surface-hover: #f3f7ff;
|
||||||
|
--tb-navbar: var(--tb-surface); /* 顶栏底色,需要时改成 var(--tb-bg) */
|
||||||
--tb-border: #e8eaee;
|
--tb-border: #e8eaee;
|
||||||
|
|
||||||
--tb-text: #1f2329;
|
--tb-text: #1f2329;
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
/* 樱花(sakura):粉调 + 细网点图案,纯 CSS 实现,不依赖图片素材。
|
/* 樱花(sakura):粉调 + 极淡网点,纯 CSS 实现,不依赖图片素材。
|
||||||
复制 _scaffold.css 写的示例:只覆盖令牌,未改动任何布局。 */
|
只覆盖令牌,不改动任何布局。要点:
|
||||||
|
- 页面底色用纯色(不用渐变),保证整页色感一致;
|
||||||
|
- 顶栏与卡片都是「带粉调的暖白」而不是纯白,和粉底之间是过渡不是硬切;
|
||||||
|
- 网点放大到 24px、透明度降到 0.05,只作纸纹,不在留白处抢注意力。 */
|
||||||
html[data-theme-style="sakura"] {
|
html[data-theme-style="sakura"] {
|
||||||
--tb-bg: #fff6f8;
|
--tb-bg: #fceef3;
|
||||||
--tb-surface: #ffffff;
|
--tb-surface: #fffafc;
|
||||||
--tb-surface-2: #fdeef2;
|
--tb-surface-2: #fbe8ee;
|
||||||
--tb-surface-hover: #fdf1f5;
|
--tb-surface-hover: #fdf1f5;
|
||||||
|
--tb-navbar: #fff6f9;
|
||||||
--tb-border: #f2dde4;
|
--tb-border: #f2dde4;
|
||||||
|
|
||||||
--tb-text: #3a2b30;
|
--tb-text: #3a2b30;
|
||||||
@@ -18,16 +22,17 @@ html[data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
--tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.14) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme="dark"][data-theme-style="sakura"] {
|
html[data-theme="dark"][data-theme-style="sakura"] {
|
||||||
--tb-bg: #241a1f;
|
--tb-bg: #241a1f;
|
||||||
--tb-surface: #2e2129;
|
--tb-surface: #2f2228;
|
||||||
--tb-surface-2: #3a2a33;
|
--tb-surface-2: #3a2a33;
|
||||||
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
--tb-surface-hover: rgba(255, 138, 176, 0.10);
|
||||||
--tb-border: #49333d;
|
--tb-navbar: #2a1e24;
|
||||||
|
--tb-border: #4a333e;
|
||||||
|
|
||||||
--tb-text: #f2e4e9;
|
--tb-text: #f2e4e9;
|
||||||
--tb-text-secondary: #c6aab4;
|
--tb-text-secondary: #c6aab4;
|
||||||
@@ -40,6 +45,6 @@ html[data-theme="dark"][data-theme-style="sakura"] {
|
|||||||
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68);
|
||||||
|
|
||||||
--tb-page-image: none;
|
--tb-page-image: none;
|
||||||
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.10) 1px, transparent 0);
|
--tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.05) 1px, transparent 1.4px);
|
||||||
--tb-page-pattern-size: 16px 16px;
|
--tb-page-pattern-size: 24px 24px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{
|
{
|
||||||
"collectionId": "tamabox",
|
"collectionId": "tamabox",
|
||||||
"collectionName": "tamabox-changelogs",
|
"collectionName": "tamabox-changelogs",
|
||||||
"content": "新增:箱主主题功能。设置页可为主题箱主页与单题页选择配色,只影响配色、图案与整页背景,不影响布局;未选择时跟随站点默认主题。<br>\n新增:主题底稿 static/css/themes/_scaffold.css,复制改名为 <slug>.css 并在 [theme] available 登记即可新增一套主题,无需改模板;示例主题「樱花」。",
|
"content": "新增:箱主主题功能。设置页可为主题选择配色、图案与整页背景(不影响布局);提问箱页面(箱主页 / 单题页 / 密码页 / 分享卡)与箱主本人后台页面都会跟随所选主题,首页、探索等公开页保持站点默认外观;未选择时跟随站点默认主题。<br>\n新增:主题底稿 static/css/themes/_scaffold.css,复制改名为 <slug>.css 并在 [theme] available 登记即可新增一套主题,无需改模板;示例主题「樱花」。",
|
||||||
"created": "2026-10-19 15:10:00.000Z",
|
"created": "2026-10-19 15:10:00.000Z",
|
||||||
"id": "none",
|
"id": "none",
|
||||||
"published_at": "2026-10-19 15:10:00.000Z",
|
"published_at": "2026-10-19 15:10:00.000Z",
|
||||||
|
|||||||
@@ -80,19 +80,12 @@ func TestGenPreview(t *testing.T) {
|
|||||||
themeBox["PageUser"].(map[string]interface{})["Background"] = bgURI
|
themeBox["PageUser"].(map[string]interface{})["Background"] = bgURI
|
||||||
themeBox["PageUser"].(map[string]interface{})["Usernamecolor"] = "#3a2b30"
|
themeBox["PageUser"].(map[string]interface{})["Usernamecolor"] = "#3a2b30"
|
||||||
themeBox["PageUser"].(map[string]interface{})["Introcolor"] = "#6b545c"
|
themeBox["PageUser"].(map[string]interface{})["Introcolor"] = "#6b545c"
|
||||||
themeCSS, err := os.ReadFile(filepath.Join("..", "static", "css", "themes", "sakura.css"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("read theme css: %v", err)
|
|
||||||
}
|
|
||||||
for _, theme := range []string{"light", "dark"} {
|
for _, theme := range []string{"light", "dark"} {
|
||||||
page, err := renderToString(t, "question/list", themeBox)
|
page, err := renderToString(t, "question/list", themeBox)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("render themed list: %v", err)
|
t.Fatalf("render themed list: %v", err)
|
||||||
}
|
}
|
||||||
// 预览页走 file://,把主题 css 内联进去(真实页面是一次带缓存的静态请求)。
|
page = inlineThemeCSS(t, page, "sakura")
|
||||||
// 用正则匹配:预览数据里没有 StaticVersion,v 参数为空串,不能按固定串替换。
|
|
||||||
link := regexp.MustCompile(`<link rel="stylesheet" href="/static/css/themes/sakura\.css\?v=[^"]*"/>`)
|
|
||||||
page = link.ReplaceAllString(page, "<style>"+string(themeCSS)+"</style>")
|
|
||||||
writePreview(t, outDir, "preview-theme-sakura-"+theme+".html", page, theme, "../static")
|
writePreview(t, outDir, "preview-theme-sakura-"+theme+".html", page, theme, "../static")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +152,40 @@ func TestGenPreview(t *testing.T) {
|
|||||||
}
|
}
|
||||||
writePreview(t, outDir, "preview-profile-account-"+theme+".html", page, theme, "../static")
|
writePreview(t, outDir, "preview-profile-account-"+theme+".html", page, theme, "../static")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置页在箱主主题下的样子:/user 后台现在也会跟随本人主题,
|
||||||
|
// 需要确认「粉色页面 + 主题选择器」不会互相吃掉。
|
||||||
|
profileSakura := profileBaseData()
|
||||||
|
profileSakura["Themes"] = profile["Themes"]
|
||||||
|
profileSakura["CurrentTheme"] = "sakura"
|
||||||
|
profileSakura["ActiveProfileTab"] = "account"
|
||||||
|
profileSakura["ThemeSlug"] = "sakura"
|
||||||
|
profileSakura["FeatureQuestion"] = nil
|
||||||
|
profileSakura["FeatureChat"] = nil
|
||||||
|
profileSakura["FeatureVote"] = nil
|
||||||
|
for _, theme := range []string{"light", "dark"} {
|
||||||
|
page, err := renderToString(t, "user/profile", profileSakura)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("render themed profile: %v", err)
|
||||||
|
}
|
||||||
|
page = inlineThemeCSS(t, page, "sakura")
|
||||||
|
writePreview(t, outDir, "preview-profile-sakura-"+theme+".html", page, theme, "../static")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inlineThemeCSS 把主题 <link> 换成内联 style:预览页走 file://,相对路径取不到。
|
||||||
|
// 预览数据里没有 StaticVersion,v 参数为空串,所以按正则匹配而不是固定串替换。
|
||||||
|
func inlineThemeCSS(t *testing.T, html, slug string) string {
|
||||||
|
t.Helper()
|
||||||
|
css, err := os.ReadFile(filepath.Join("..", "static", "css", "themes", slug+".css"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read theme css: %v", err)
|
||||||
|
}
|
||||||
|
link := regexp.MustCompile(`<link rel="stylesheet" href="/static/css/themes/` + slug + `\.css\?v=[^"]*"/>`)
|
||||||
|
if !link.MatchString(html) {
|
||||||
|
t.Fatalf("主题 %s 的 <link> 未出现在页面里(ThemeSlug 没传到模板)", slug)
|
||||||
|
}
|
||||||
|
return link.ReplaceAllString(html, "<style>"+string(css)+"</style>")
|
||||||
}
|
}
|
||||||
|
|
||||||
// writePreview 把 CDN 换成可直连的镜像、钉死主题,仅用于本地预览。
|
// writePreview 把 CDN 换成可直连的镜像、钉死主题,仅用于本地预览。
|
||||||
|
|||||||