fix(layout): align color scheme, content width and fonts with reference theme

- Color scheme: zibll field order/labels, theme_skin_custom overrides palette,
  hex palette swatches, dark_theme_skin_custom, light/dark background images,
  close_backdrop via body.fps-accelerat, theme_main_radius drives --main-radius
- Emit --theme-color / --focus-shadow-color / --focus-color-opacity* vars
- Drop border_radius, primary_color readers and legacy value maps
- Content max width: free 1200-2200 number field; fix font family/custom stack

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-10-28 19:36:11 +08:00
1 parent 6da08d9d4f
commit 74021d26bb
8 files changed
+319 -221

No files matched your search

+59 -56
View File
@@ -345,10 +345,6 @@ class ThemeSearch {
public static function theme_mode(): string {
$mode = sanitize_key((string) Settings::get_value('theme_mode', 'time-auto'));
$map = ['light' => 'white-theme', 'dark' => 'dark-theme', 'auto' => 'time-auto'];
if (isset($map[$mode])) {
return $map[$mode];
}
$valid = ['white-theme', 'dark-theme', 'time-auto'];
return in_array($mode, $valid, true) ? $mode : 'time-auto';
}
@@ -392,68 +388,71 @@ class ThemeSearch {
return '';
}
public static function primary_color(): string {
$color = trim((string) Settings::get_value('primary_color', '#f04494'));
return preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $color) ? $color : '#f04494';
private const HEX_PATTERN = '/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/';
/** 全局主题色:theme_skin_custom 优先,清空时使用 theme_skin 预置色(对齐参考主题 zib_head_css)。 */
public static function theme_color(): string {
$custom = trim((string) Settings::get_value('theme_skin_custom', ''));
if (preg_match(self::HEX_PATTERN, $custom)) {
return $custom;
}
$skin = ltrim(trim((string) Settings::get_value('theme_skin', 'f04494')), '#');
return preg_match('/^[0-9a-fA-F]{6}$/', $skin) ? '#' . $skin : '#f04494';
}
public static function theme_skin(): string {
$skin = trim((string) Settings::get_value('theme_skin', 'f04494'));
$skin = ltrim($skin, '#');
if (preg_match('/^[0-9a-fA-F]{6}$/', $skin)) {
return '#' . $skin;
}
$legacy_map = [
'pink' => '#f04494',
'blue' => '#627bf5',
'green' => '#36af18',
'purple' => '#ae53f3',
'custom' => '',
];
if (isset($legacy_map[$skin])) {
return $legacy_map[$skin] !== '' ? $legacy_map[$skin] : self::primary_color();
}
return self::primary_color();
}
public static function dark_primary_color(): string {
$color = trim((string) Settings::get_value('dark_primary_color', ''));
if (preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $color)) {
return $color;
}
return self::primary_color();
/** 夜间模式主题色;未设置返回空串,夜间沿用全局主题色。 */
public static function dark_theme_color(): string {
$color = trim((string) Settings::get_value('dark_theme_skin_custom', ''));
return preg_match(self::HEX_PATTERN, $color) ? $color : '';
}
public static function get_theme_mode_button_positions(): array {
$raw = Settings::get_value('theme_mode_button', ['pc_nav', 'm_menu']);
if (is_array($raw)) {
return array_values(array_filter(array_map('sanitize_text_field', $raw)));
}
if (is_bool($raw)) {
return $raw ? ['pc_nav', 'm_menu'] : [];
}
$str = trim((string) $raw);
if ($str === '' || $str === '0') return [];
$items = preg_split('/[,|]+/', $str) ?: [];
return array_values(array_filter(array_map('sanitize_text_field', $items)));
return array_values(array_intersect(array_map('sanitize_key', (array) $raw), ['pc_nav', 'm_menu']));
}
public static function resolved_primary_color(): string {
$skin = self::theme_skin();
return $skin !== '' ? $skin : self::primary_color();
/** 卡片圆角 theme_main_radius(0–30,默认 12)→ --main-radius。 */
public static function main_radius(): int {
return max(0, min(30, (int) Settings::get_value('theme_main_radius', 12)));
}
public static function border_radius(): int {
$radius = (int) Settings::get_value('border_radius', 8);
return max(0, min(20, $radius));
public static function close_backdrop(): bool {
return !empty(Settings::get_value('close_backdrop', false));
}
public static function card_radius(): int {
$main = Settings::get_value('theme_main_radius', null);
if ($main !== null && $main !== '') {
return max(0, min(30, (int) $main));
/**
* 背景图 CSS 声明(不含选择器);无颜色且无图片时返回空串。
* 子键白名单与 GlobalSchema::background_field() / layout.js bgField 一致。
*/
public static function background_css(string $key): string {
$bg = Settings::get_value($key, []);
if (!is_array($bg)) {
return '';
}
return self::border_radius() + 4;
$color = trim((string) ($bg['color'] ?? ''));
$color = preg_match(self::HEX_PATTERN, $color) ? $color : '';
$image = esc_url_raw(trim((string) ($bg['image'] ?? '')));
if ($color === '' && $image === '') {
return '';
}
$allowed = [
'position' => ['left top', 'left center', 'left bottom', 'center top', 'center center', 'center bottom', 'right top', 'right center', 'right bottom'],
'repeat' => ['repeat', 'no-repeat', 'repeat-x', 'repeat-y'],
'attachment' => ['scroll', 'fixed'],
'size' => ['100%', 'cover', 'contain', 'auto'],
'origin' => ['padding-box', 'border-box', 'content-box'],
];
$css = $color !== '' ? 'background-color:' . $color . ';' : '';
if ($image !== '') {
$css .= 'background-image:url("' . str_replace(['"', '\\', "\n", "\r"], '', $image) . '");';
foreach ($allowed as $prop => $values) {
$value = (string) ($bg[$prop] ?? '');
if (in_array($value, $values, true)) {
$css .= 'background-' . $prop . ':' . $value . ';';
}
}
}
return $css;
}
public static function is_qj_loading_enabled(): bool {
@@ -470,9 +469,6 @@ class ThemeSearch {
public static function container_max_width(): int {
$width = (int) Settings::get_value('container_max_width', 1200);
if ($width === 0) {
return 0;
}
return max(1200, min(2200, $width));
}
@@ -481,6 +477,13 @@ class ThemeSearch {
return in_array($family, ['system', 'noto-sans-sc', 'noto-serif-sc', 'custom'], true) ? $family : 'system';
}
/** 自定义 font-family 字体栈,只保留字体名、引号、逗号等安全字符。 */
public static function font_family_custom(): string {
$stack = (string) Settings::get_value('font_family_custom', '');
$stack = preg_replace('/[^\p{L}\p{N}\s,"\'\-_.]/u', '', $stack);
return trim((string) preg_replace('/\s+/', ' ', (string) $stack), " ,");
}
public static function get_code_highlight_config(): array {
$s = Settings::get_all();