2026-10-23 10:35:56 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 自定义代码(CSS / JS)
|
|
|
|
|
|
*
|
|
|
|
|
|
* 这两段代码存在主题选项里(数据库 wp_options 的 kratos 项),不存主题目录。
|
|
|
|
|
|
* 原因:WordPress 升级/更新主题时会**清空整个主题目录**再解压
|
|
|
|
|
|
* (wp-admin/includes/class-theme-upgrader.php 里 clear_destination = true,
|
|
|
|
|
|
* 随后 delete_old_theme() 递归删除),写在主题目录里的任何自定义文件都会丢。
|
|
|
|
|
|
* 放进选项表就与主题文件解耦,升级、重装、换主题目录名都不影响。
|
|
|
|
|
|
*
|
2026-10-23 12:55:41 +08:00
|
|
|
|
* @author Yongquan Yang <yangyq.net>
|
2026-10-23 10:35:56 +08:00
|
|
|
|
* @license MIT License
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-10-25 10:36:29 +08:00
|
|
|
|
* 默认自定义 CSS:空。
|
2026-10-23 10:35:56 +08:00
|
|
|
|
*
|
2026-10-25 10:36:29 +08:00
|
|
|
|
* 历史沿革(3.2.29 变更):
|
|
|
|
|
|
* 早年主题目录下有个 custom 子目录当「自定义样式」入口,后来改成配置项,
|
|
|
|
|
|
* 那批规则(段落缩进、h2 蓝条、列表缩进)就作为默认值下发,并被写进了库。
|
|
|
|
|
|
* 3.2.29 把它们并入主题公共样式 assets/css/site.css,配置项改为默认空 ——
|
|
|
|
|
|
* 「站点通用样式」本该跟着主题走,「自定义代码」留给临时覆盖。
|
2026-10-23 10:35:56 +08:00
|
|
|
|
*
|
2026-10-25 10:36:29 +08:00
|
|
|
|
* ⚠️ 不要再用旧的那段 CSS 给配置项兜底:site.css 已经在输出同样的规则,
|
|
|
|
|
|
* 再兜底一次就等于全站样式写两遍,且会让后台的框永远显示旧内容。
|
2026-10-23 10:35:56 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function yang_default_custom_css()
|
2026-10-25 10:36:29 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 3.2.29 之前作为默认值下发、并已写进数据库的那段 CSS。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 只用于两件事:
|
|
|
|
|
|
* ① 识别「库里存的还是历史默认值」——输出时跳过,避免与 site.css 重复;
|
|
|
|
|
|
* ② 迁移时比对,确认是可以安全清空的那一份(不是站长自己改过的内容)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 这里有意保留原样的换行与缩进:比对前会先做空白归一化,
|
|
|
|
|
|
* 所以即使库里的换行是 CRLF、这里的是 LF,也能正确匹配。
|
|
|
|
|
|
*/
|
|
|
|
|
|
function yang_legacy_custom_css()
|
2026-10-23 10:35:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
return <<<'CSS'
|
|
|
|
|
|
.article .content p{ text-indent:2em }
|
|
|
|
|
|
.k-main .details .article .content h2 {
|
|
|
|
|
|
margin: 16px -16px;
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
border-left: 5px solid #00a2ff;
|
|
|
|
|
|
background-color: rgba(243, 243, 243, 0.7);
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
line-height: 41px;
|
|
|
|
|
|
}
|
|
|
|
|
|
ul{
|
|
|
|
|
|
margin-left:2em;
|
|
|
|
|
|
}
|
|
|
|
|
|
ol{
|
|
|
|
|
|
margin-left:2em;
|
|
|
|
|
|
}
|
|
|
|
|
|
ol > li{
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
}
|
|
|
|
|
|
ul > li{
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CSS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-10-25 10:36:29 +08:00
|
|
|
|
* CSS 空白归一化:只用于「是不是同一段代码」的比对,不用于输出。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 处理:CRLF/CR → LF、连续空白压成一个空格、去掉 `{ } : ; , >` 两侧空白、
|
|
|
|
|
|
* 去掉块尾多余的 `;`。这样「同一条规则的不同缩进/换行」会得到同一个字符串。
|
|
|
|
|
|
*/
|
|
|
|
|
|
function yang_normalize_css($css)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!is_string($css)) {
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
$css = str_replace(array("\r\n", "\r"), "\n", $css);
|
|
|
|
|
|
$css = preg_replace('/\s+/', ' ', $css);
|
|
|
|
|
|
$css = preg_replace('/\s*([{}:;,>])\s*/', '$1', $css);
|
|
|
|
|
|
$css = str_replace(';}', '}', $css);
|
|
|
|
|
|
return trim($css);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 库里存的这段 CSS 是否就是「已并入 site.css 的历史默认值」。
|
|
|
|
|
|
*/
|
|
|
|
|
|
function yang_is_legacy_custom_css($css)
|
|
|
|
|
|
{
|
|
|
|
|
|
$normalized = yang_normalize_css($css);
|
|
|
|
|
|
return $normalized !== '' && $normalized === yang_normalize_css(yang_legacy_custom_css());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 取自定义 CSS(未设置时为空)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 历史默认值已被 site.css 接管:库里若还是它,这里返回空串,
|
|
|
|
|
|
* 避免同一批规则在页面上出现两遍。真正自己改过的内容原样返回。
|
2026-10-23 10:35:56 +08:00
|
|
|
|
*/
|
|
|
|
|
|
function yang_custom_css()
|
|
|
|
|
|
{
|
|
|
|
|
|
$css = kratos_option('g_custom_css', yang_default_custom_css());
|
2026-10-25 10:36:29 +08:00
|
|
|
|
if (!is_string($css)) {
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
if (yang_is_legacy_custom_css($css)) {
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
return $css;
|
2026-10-23 10:35:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 取自定义 JS(未设置时为空)
|
|
|
|
|
|
*/
|
|
|
|
|
|
function yang_custom_js()
|
|
|
|
|
|
{
|
|
|
|
|
|
$js = kratos_option('g_custom_js', '');
|
|
|
|
|
|
return is_string($js) ? $js : '';
|
2026-10-25 10:36:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 一次性迁移:把库里那段「历史默认 CSS」清成空串。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 为什么需要:std / 默认值只在「后台预填」和「恢复默认」时起作用,
|
|
|
|
|
|
* 运行时 kratos_option() 只查库 —— 库里的旧值不清,后台那个框就永远
|
|
|
|
|
|
* 显示着已经并入 site.css 的旧内容,站长以为它还在生效。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 为什么挂在 admin_init:
|
|
|
|
|
|
* · 只影响后台请求,前台一个写操作都不做;
|
|
|
|
|
|
* · 用户升级后第一次进后台就自动完成,不需要额外操作。
|
|
|
|
|
|
*
|
|
|
|
|
|
* ⚠️ 三条护栏:
|
|
|
|
|
|
* ① 有 $_POST 时直接退出 —— 本函数会走 update_option(),而 update_option()
|
|
|
|
|
|
* 内部会跑 sanitize_option_kratos(= validate_options)。那个回调看到
|
|
|
|
|
|
* $_POST['reset'] 会返回「全部默认值」⇒ 用户在后台点保存/恢复默认的
|
|
|
|
|
|
* 那一下,配置会被我们顺手改成默认值。所以提交请求里绝不插手。
|
|
|
|
|
|
* ② 只清「与历史默认值逐字等价」的内容 —— 站长自己改过的一个字都不碰。
|
|
|
|
|
|
* ③ 清空而不是删键:删键会被 validate_options 用库里的旧值补回来。
|
|
|
|
|
|
*/
|
|
|
|
|
|
function yang_custom_code_migrate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!empty($_POST)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
$saved = get_option('kratos');
|
|
|
|
|
|
if (!is_array($saved) || !isset($saved['g_custom_css'])) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!yang_is_legacy_custom_css($saved['g_custom_css'])) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
$saved['g_custom_css'] = '';
|
|
|
|
|
|
update_option('kratos', $saved);
|
|
|
|
|
|
}
|
|
|
|
|
|
add_action('admin_init', 'yang_custom_code_migrate');
|