* @license MIT License * @version 2020.09.21 */ function getrobots() { $site_url = parse_url(site_url()); $path = (!empty($site_url['path'])) ? $site_url['path'] : ''; $robots = "User-agent: *\n\n"; $robots .= "Disallow: $path/wp-admin/\n"; $robots .= "Disallow: $path/wp-includes/\n"; $robots .= "Disallow: $path/wp-content/plugins/\n"; $robots .= "Disallow: $path/wp-content/themes/\n"; return $robots; } /** * 图片字段的默认值(后台预填用)。 * * ── 为什么不直接调 yang_image_default() ────────────────────── * 本文件由 optionsframework_init() 在 init 钩子上 require, * 而 yang_image_default() 来自 inc/theme-option-defaults.php。 * 正常时序下后者先加载,但**加载顺序被打乱时**(子主题、外部脚本 * 直接 include 本文件、插件在更早的钩子里触发本函数), * 直接调用就会 Fatal —— 后台整个白屏,比"少一个预填值"严重得多。 * * 这里先用 function_exists() 探一下,缺了就返回空串: * 后台退化成没有预填默认值,但页面能打开、能保存、能干活。 * 降级必须降到"还能用",不能降到"打不开"。 */ if (!function_exists('yang_options_default_img')) { function yang_options_default_img($id) { return function_exists('yang_image_default') ? yang_image_default($id) : ''; } } /** * 哀悼相关辅助函数的安全访问 * * 同样的道理:yang_mourning_presets() / yang_mourning_status_text() / * yang_mourning_extra_raw() 都在 inc/theme-mourning.php 里,由 * functions.php 按顺序 require。只要有人(子主题、迁移脚本、别的插件) * 在 theme-mourning.php 之前触发了 kratos_options(),这里就会 Fatal, * 整个后台白屏,且报错指向本文件,很难联想到是加载顺序问题。 * * 降级策略:缺函数时按"没有纪念日 / 没有状态说明"降级 —— * 后台那几个控件会变空,但页面能打开、能保存、能继续用。 */ if (!function_exists('yang_opt_mourning_presets')) { function yang_opt_mourning_presets() { return function_exists('yang_mourning_presets') ? yang_mourning_presets() : array(); } } if (!function_exists('yang_opt_mourning_status')) { function yang_opt_mourning_status() { return function_exists('yang_mourning_status_text') ? yang_mourning_status_text() : ''; } } if (!function_exists('yang_opt_mourning_extra_raw')) { function yang_opt_mourning_extra_raw() { return function_exists('yang_mourning_extra_raw') ? yang_mourning_extra_raw() : ''; } } /** * 今年清明的月日,给后台说明文字用(如「4 月 5 日」) * * 换算不出来(超出年份表范围)时返回一句明确的说明, * **不要**退化成「4 月 4 日」—— 那正是用户要求删掉的近似值。 */ if (!function_exists('yang_opt_qingming_label')) { function yang_opt_qingming_label() { if (!function_exists('yang_qingming_md')) { return __('换算不可用', 'kratos'); } $md = yang_qingming_md(); if ($md === null) { return sprintf( __('今年(%s 年)超出可换算范围,清明不会自动生效', 'kratos'), current_time('Y') ); } list($mo, $da) = explode('-', $md); return sprintf(__('%d 月 %d 日', 'kratos'), (int) $mo, (int) $da); } } /** * 自定义 CSS 的默认值(来自 inc/theme-custom-code.php) * * 同样是加载顺序问题:这个函数在 theme-custom-code.php 里, * 而 kratos_options() 可能被更早触发。缺了就返回空串, * 后台的「自定义 CSS」框是空的,但能打开、能填、能保存。 * * 3.2.29 起该默认值恒为空:原来的那批规则(段落缩进、h2 蓝条、列表缩进) * 已并入主题公共样式 assets/css/site.css,配置项只留给站长做临时覆盖。 */ if (!function_exists('yang_opt_default_custom_css')) { function yang_opt_default_custom_css() { return function_exists('yang_default_custom_css') ? yang_default_custom_css() : ''; } } function kratos_options() { $sitename = get_bloginfo('name'); $imagepath = ASSET_PATH . '/assets/img/options/'; $seorobots = 'robots.txt'; $seoreading = '' . __('设置-阅读-对搜索引擎的可见性', 'kratos') . ''; $top_array = array( 'banner' => __( '图片导航', 'kratos' ), 'color' => __( '颜色导航', 'kratos' ), ); $options = array(); /* ══════════════════════════════════════════════════════════ * 一、全站配置 —— 影响每一个页面的东西 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('全站配置', 'kratos'), 'type' => 'heading', ); $options[] = array( 'name' => __('图片 Logo', 'kratos'), 'desc' => __('不选择图片则显示文字标题', 'kratos'), 'id' => 'g_logo', 'type' => 'upload', /* 有意不设 std:这里空着时显示站点名称文字,比塞一张通用占位 logo 好看。其它图片字段见 inc/theme-option-defaults.php。 */ ); $options[] = array( 'name' => __('Favicon 图片', 'kratos'), 'desc' => __('浏览器收藏夹和地址栏中显示的图标。留空则自动使用主题自带的默认图标,不会出现空白。', 'kratos'), 'id' => 'g_icon', /* 有意不写 std。 * * std 里存的是**绝对 URL**,一旦用户保存表单就会被写进数据库。 * 数据库里躺着一个写死的主题目录地址是隐患:主题目录改名、 * 换 CDN、或站点迁移域名之后,那条记录就指向不存在的文件, * 页面上是破图,而用户在后台看到的仍是"已设置",很难自己发现。 * * 所以默认值一律由运行时提供(yang_option_image()),库里保持空。 * 这样默认图地址永远由当前请求现算,改目录也不用改数据。 */ 'type' => 'upload', ); $options[] = array( 'name' => __('背景颜色', 'kratos'), 'desc' => __('全站页面的背景颜色,需填写十六进制颜色码', 'kratos'), 'id' => 'g_background', 'std' => '#f5f5f5', 'type' => 'color', ); $options[] = array( 'name' => __('Chrome 导航栏颜色', 'kratos'), 'desc' => __('Chrome 移动端浏览器地址栏的颜色', 'kratos'), 'id' => 'g_chrome', 'std' => '#282a2c', 'type' => 'color', ); $options[] = array( 'name' => __('404 页面图片', 'kratos'), 'desc' => __('访客打开不存在的地址时显示的配图', 'kratos'), 'id' => 'g_404', 'std' => yang_options_default_img('g_404'), 'type' => 'upload', ); $options[] = array( 'name' => __('前台管理员导航', 'kratos'), 'desc' => __('登录管理员后,页面顶部显示 WordPress 管理工具条', 'kratos'), 'std' => '1', 'id' => 'g_adminbar', 'type' => 'checkbox', ); $options[] = array( 'name' => __('CSS 动画库', 'kratos'), 'desc' => __('开启 animate.css 效果。会增加一个约 60KB 的样式文件,不需要就别开。', 'kratos'), 'std' => '0', 'id' => 'g_animate', 'type' => 'checkbox', ); $options[] = array( 'name' => __('Gravatar 加速', 'kratos'), 'desc' => __('把评论头像的请求转发到国内可访问的镜像,改善加载速度。若开启了下面的「自动头像」,未上传头像的访客不再需要这张图。', 'kratos'), 'std' => '0', 'id' => 'g_gravatar', 'type' => 'checkbox', ); $options[] = array( 'name' => __('禁止生成缩略图', 'kratos'), 'desc' => __('上传图片时不再额外生成多种尺寸的副本,节省磁盘空间', 'kratos'), 'id' => 'g_removeimgsize', 'std' => '0', 'type' => 'checkbox', ); $options[] = array( 'name' => __('Gutenberg 编辑器', 'kratos'), 'desc' => __('开启 WordPress 区块编辑器。关闭则使用经典编辑器。', 'kratos'), 'std' => '0', 'id' => 'g_gutenberg', 'type' => 'checkbox', ); /* ══════════════════════════════════════════════════════════ * 二、自动头像 —— 独立一块 * * 3.2.36 里这两项原本塞在「全站配置」内部(Gravatar 加速之后)。 * 上线后发现**根本找不到**:它排在第 9 位,纵坐标 1058px,而 * 浏览器视口才 1000px 高 —— 前 8 项(其中「404 页面图片」一项 * 就占 301px)把它顶到首屏之外,不往下滚看不见。左侧标签栏也没 * 有「头像」字样,光扫标签栏同样摸不着。 * * 所以提成独立标签页:标签栏直接能看见,进去第一项就是开关。 * 这也更贴合原始需求「最上面的一个复选框,勾完之后出现下面这些 * 列表」——独立成页后,这个「上面/下面」的关系才真的成立。 * * ── 为什么开关与风格拆成两个字段 ────────────────────────── * 若用一个字段直接存风格名(留空=关闭),用户「主动关闭」和 * 「还没选过风格」在库里会变成同一种状态(都空),以后想恢复 * 默认值时分不清该填什么。两个字段各管一件事更清楚。 * * ⚠️ std 只在后台预填和「恢复默认」时起作用,运行时 kratos_option() * 完全不看它。所以运行时默认值必须同步给一份: * 开关默认关('0'),风格默认 lorelei(见 yang_avatar_style())。 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('自动头像', 'kratos'), 'type' => 'heading', ); $options[] = array( 'name' => __('启用自动头像', 'kratos'), 'desc' => __('访客没注册、也没上传头像时,按他的邮箱生成一张头像。全程本地生成,不请求任何外部服务,同一个邮箱永远得到同一张。若访客已经上传过真实头像,不受影响。', 'kratos'), 'std' => '0', 'id' => 'a_auto_enable', 'type' => 'checkbox', ); $options[] = array( 'name' => __('头像风格', 'kratos'), 'desc' => __('勾选上面的「启用自动头像」后,这里才会出现风格列表。所有风格都可自由使用与商用,且不要求署名。点一下即时预览,保存后生效。', 'kratos'), 'std' => 'lorelei', 'id' => 'a_auto_style', 'type' => 'avatar_style', /* 只有开关打开时才显示这个控件;关着的时候看不到它, 避免用户在关闭状态下改了风格却不知道为什么没生效。 */ 'requires' => 'a_auto_enable', ); /* ══════════════════════════════════════════════════════════ * 三、顶部导航 —— 页头那一条 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('顶部导航', 'kratos'), 'type' => 'heading', ); $options[] = array( 'name' => __( '顶部样式', 'kratos' ), 'desc' => __('请选择顶部样式(图片导航或颜色导航)', 'kratos'), 'id' => 'top_select', 'std' => 'banner', 'type' => 'select', 'options' => $top_array ); $options[] = array( 'name' => __('图片导航背景', 'kratos'), 'desc' => __('顶部样式选「图片导航」时使用。留空则自动使用主题自带的默认图片。', 'kratos'), 'id' => 'top_img', 'std' => yang_options_default_img('top_img'), 'class' => 'hidden', 'type' => 'upload', ); $options[] = array( 'name' => __('颜色导航背景', 'kratos'), 'desc' => __('顶部样式选「颜色导航」时使用', 'kratos'), 'id' => 'top_color', 'std' => '#24292e', 'class' => 'hidden', 'type' => 'color', ); $options[] = array( 'name' => __('副标题', 'kratos'), 'desc' => __('显示在站点标题旁边的一句短话', 'kratos'), 'id' => 'top_title', 'std' => 'Kratos', 'class' => 'hidden', 'type' => 'text', ); $options[] = array( 'name' => __('标题描述', 'kratos'), 'std' => __('一款专注于用户阅读体验的响应式博客主题', 'kratos'), 'id' => 'top_describe', 'class' => 'hidden', 'type' => 'text', ); /* ══════════════════════════════════════════════════════════ * 四、首页配置 —— 只管首页列表长什么样 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('首页配置', 'kratos'), 'type' => 'heading', ); $options[] = array( 'name' => __('特色图片', 'kratos'), 'desc' => __('在首页文章列表的每篇标题上方显示一张配图', 'kratos'), 'std' => '1', 'id' => 'g_thumbnail', 'type' => 'checkbox', ); $options[] = array( 'name' => __('默认特色图', 'kratos'), 'desc' => __('文章既没有正文图片、也没有设置特色图时,用这张顶上。留空则自动使用主题自带的默认图片。', 'kratos'), 'id' => 'g_postthumbnail', 'class' => 'hidden', 'std' => yang_options_default_img('g_postthumbnail'), 'type' => 'upload', ); $options[] = array( 'name' => __('无内容图片', 'kratos'), 'desc' => __('搜索不到结果、或分类下还没有文章时显示的插画。留空则自动使用主题自带的默认图片。', 'kratos'), 'id' => 'g_nothing', 'std' => yang_options_default_img('g_nothing'), 'type' => 'upload', ); /* ══════════════════════════════════════════════════════════ * 五、文章配置 —— 打开单篇文章才看得到的东西 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('文章配置', 'kratos'), 'type' => 'heading', ); $options[] = array( 'name' => __('页面布局', 'kratos'), 'desc' => __('文章页面是否显示侧边栏。仅在文章详情页生效。', 'kratos'), 'id' => "g_article_widgets", 'std' => "two_side", 'type' => "images", 'options' => array( 'one_side' => $imagepath . 'col-12.png', 'two_side' => $imagepath . 'col-8.png') ); $options[] = array( 'name' => __('文章打赏', 'kratos'), 'desc' => __('在文章底部显示打赏按钮,点开是收款二维码', 'kratos'), 'id' => 'g_donate', 'type' => 'checkbox', ); $options[] = array( 'name' => __('支付宝收款码', 'kratos'), 'desc' => __('留空则自动使用主题自带的默认图片。', 'kratos'), 'id' => 'g_donate_alipay', 'std' => yang_options_default_img('g_donate_alipay'), 'type' => 'upload', 'class' => 'hidden', ); $options[] = array( 'name' => __('微信收款码', 'kratos'), 'desc' => __('留空则自动使用主题自带的默认图片。', 'kratos'), 'id' => 'g_donate_wechat', 'std' => yang_options_default_img('g_donate_wechat'), 'type' => 'upload', 'class' => 'hidden', ); /* ══════════════════════════════════════════════════════════ * 六、自动目录 —— 把长文切成能跳的章节 * * 与「文章配置」分开成独立标签页,是刻意的:目录的选项有六项, * 塞进文章配置里会把「页面布局 / 打赏」这些一眼要看到的东西挤下去。 * * ⚠️ 这里的 std 必须与 inc/theme-toc.php 的 yang_toc_defaults() 一致。 * 前者只服务「后台预填」和「恢复默认」,运行时一律走 * kratos_option($id, 默认值) —— 两处不一致会出现 * 「页面照 A 渲染、后台框里显示 B」的错位,而且极难发现。 * ══════════════════════════════════════════════════════════ */ $options[] = array( 'name' => __('自动目录', 'kratos'), 'type' => 'heading', ); /* ── 分组标题:正文里的那一份 ────────────────────────────── * * 用 info 类型而不是 heading:heading 会另起一个标签页 * (framework 里 `case "heading"` 会 $counter++ 并新建 * #options-group-N),info 只渲染成一行
** ——
写 会被静默剥掉,页面上只剩裸文字。所以这里用 强调。 */
__('变黑白时,页面顶部会出现一条提示,点进去是一个说明页面(彩色),讲清楚为什么变黑白、哪几天会变。
这里可以改那个页面的路径。留空默认 memory,即 %s
注意:不要和已有文章或页面的路径重名。', 'kratos'),
esc_url(home_url('/memory/'))
),
'id' => 'g_rip_page_slug',
'std' => 'memory',
'type' => 'text',
);
$options[] = array(
'desc' => yang_opt_mourning_status(),
'type' => 'info',
);
/* ══════════════════════════════════════════════════════════
* 十、收录与统计 —— 给搜索引擎看的
* ══════════════════════════════════════════════════════════ */
$options[] = array(
'name' => __('收录与统计', 'kratos'),
'type' => 'heading',
);
$options[] = array(
'name' => __('分享图片', 'kratos'),
'desc' => __('搜索引擎或者社交工具分享首页时抓取的图片。留空则自动使用主题自带的默认图片。', 'kratos'),
'id' => 'seo_shareimg',
'std' => yang_options_default_img('seo_shareimg'),
'type' => 'upload',
);
$options[] = array(
'name' => __('关键词', 'kratos'),
'desc' => __('每个关键词之间需要用「英文逗号」分割', 'kratos'),
'id' => 'seo_keywords',
'type' => 'text',
);
$options[] = array(
'name' => __('站点描述', 'kratos'),
'id' => 'seo_description',
'type' => 'textarea',
);
$options[] = array(
'name' => __('统计代码', 'kratos'),
'desc' => __('填在页脚的统计脚本(如站点访问量统计)。注意:输入 HTML/JS 代码时请注意辨别代码安全!', 'kratos'),
'id' => 'seo_statistical',
'type' => 'textarea',
);
$options[] = array(
'name' => __('robots.txt 内容', 'kratos'),
'desc' => __('- 需要 ', 'kratos') . $seoreading . __(' 是开启的状态,下面的配置才会生效', 'kratos'),
'type' => 'info',
);
$options[] = array(
'desc' => __('- 如果网站根目录下已经有 robots.txt 文件,下面的配置不会生效', 'kratos'),
'type' => 'info',
);
$options[] = array(
'desc' => __('- 点击 ', 'kratos') . $seorobots . __(' 查看配置是否生效,如果网站开启了 CDN,可能需要刷新缓存才会生效', 'kratos'),
'type' => 'info',
);
$options[] = array(
'id' => 'seo_robots',
'std' => getrobots(),
'type' => 'textarea',
);
/* ══════════════════════════════════════════════════════════
* 十一、邮件通知 —— SMTP 与评论提醒
* ══════════════════════════════════════════════════════════ */
$options[] = array(
'name' => __('邮件通知', 'kratos'),
'type' => 'heading',
);
$options[] = array(
'name' => __('SMTP 服务', 'kratos'),
'desc' => __('用第三方邮箱发信。不开启时走服务器本地发信,很多主机上会被判定为垃圾邮件。', 'kratos'),
'id' => 'm_smtp',
'type' => 'checkbox',
);
$options[] = array(
'name' => __('邮件服务器', 'kratos'),
'desc' => __('填写发件服务器地址', 'kratos'),
'id' => 'm_host',
'class' => 'hidden',
'type' => 'text',
);
$options[] = array(
'name' => __('服务器端口', 'kratos'),
'desc' => __('填写发件服务器端口', 'kratos'),
'id' => 'm_port',
'class' => 'hidden',
'type' => 'text',
);
$options[] = array(
'name' => __('授权方式', 'kratos'),
'desc' => __('填写登录鉴权的方式,ssl 或 tls', 'kratos'),
'id' => 'm_sec',
'class' => 'hidden',
'type' => 'text',
);
$options[] = array(
'name' => __('邮箱帐号', 'kratos'),
'desc' => __('填写邮箱账号', 'kratos'),
'id' => 'm_username',
'class' => 'hidden',
'type' => 'text',
);
$options[] = array(
'name' => __('邮箱密码', 'kratos'),
'desc' => __('填写邮箱密码或授权码', 'kratos'),
'id' => 'm_passwd',
'class' => 'hidden',
'type' => 'password',
);
$options[] = array(
'id' => 'm_sendmail',
'class' => 'hidden',
'type' => 'sendmail',
);
/* ── 评论提醒的开关 ──────────────────────────────────────
*
* ⚠️ 这三个开关原先**只有代码在读取、后台没有界面**:
* `m_comment_notify` —— 有人回复时通知被回复者
* `m_comment_approved_notify` —— 评论通过审核时通知评论者
* `m_keep_core_notify` —— 保留 WordPress 自带的作者通知
* 也就是说用户无法关掉它们,只能改代码。
* 静态契约检查(`_static_315.php`)会报「模板读取的选项都有界面」失败,
* 那一项正是靠这个抓出来的。
*
* 默认值取 true 与代码里的 `kratos_option('m_comment_notify', true)` 一致:
* 评论提醒默认开着(这是博客的基本礼貌),想关的人自己能关。
*/
$options[] = array(
'name' => __('有人回复时发邮件通知', 'kratos'),
'desc' => __('评论收到回复时,给被回复的人发一封提醒。需要先在下面配好发信方式,否则发不出去。', 'kratos'),
'id' => 'm_comment_notify',
'std' => true,
'type' => 'checkbox',
);
$options[] = array(
'name' => __('评论通过审核时通知评论者', 'kratos'),
'desc' => __('评论从「待审核」变为「已通过」时,告诉评论者他的评论已显示。适合开了先审后发的站点。', 'kratos'),
'id' => 'm_comment_approved_notify',
'std' => true,
'type' => 'checkbox',
);
$options[] = array(
'name' => __('保留 WordPress 自带的作者通知', 'kratos'),
'desc' => __('主题在装了评论插件时会关掉 WordPress 自带的「有新评论通知站长」,避免和插件重复发信。只有当插件在场时勾这一项才有意义;插件不在场时主题一定会保留自带通知,不会让你收不到信。', 'kratos'),
'id' => 'm_keep_core_notify',
'std' => false,
'type' => 'checkbox',
);
/* ══════════════════════════════════════════════════════════
* 十二、CDN 加速 —— 一个开关 + 两个名单
*
* 3.2.34 原设计是「地址留空即关闭」,没有开关。本版(3.2.35)
* 按用户要求补了三件事:
* ① 「启用 CDN 加速」复选框,作为总开关
* ② 白名单预填 13 类静态资源后缀(用户可改)
* ③ 黑名单预填安全相关后缀(用户可改)
*
* ── 预制内容为什么放在输入框里而不是硬编码 ──────────────────
* 用户明确选了这条路:「预制的这些就放在白名单的输入框里,
* 这样用户就可以直接修改;修改完之后,我们再把它保存下来,
* 按照用户修改的来执行。」
*
* 所以预制内容写在 std 里 —— 它只服务两件事:
* · 后台首次渲染时预填
* · 点「恢复默认」时还原成这份内容
* 一旦用户保存过,库里就有明确的值,运行时读的是库里的值,
* 主题**不会**再去覆盖用户改过的内容。
*
* 匹配逻辑(写进说明里,让用户看得到):
* 开关没勾 → 整个功能关闭,两套名单都不参与
* 先看黑名单 → 命中就保持原地址
* 黑名单没命中 → 再看白名单
* 黑名单优先级高于白名单
* ══════════════════════════════════════════════════════════ */
$options[] = array(
'name' => __('CDN 加速', 'kratos'),
'type' => 'heading',
);
/*
* 开关必须是本段的第一个控件。
*
* std 用 yang_cdn_enable_default()(地址非空 ⇒ 默认勾选),
* 目的是**老站点升级不丢加速**:3.2.34 的站点只要填过地址就
* 一直在加速,升级后若默认不勾,它会静默失去加速,而用户不会
* 去查一个从没动过的复选框。
*/
$options[] = array(
'name' => __('启用 CDN 加速', 'kratos'),
'desc' => __('勾选后功能才生效。没勾时,下面填什么都不产生作用,前台与不装这个功能完全一致。'
. '
勾了但 CDN 地址留空是不允许的:点保存会被拦下来并提示必须填地址。', 'kratos'),
'id' => 'cdn_enable',
'std' => function_exists('yang_cdn_enable_default') ? yang_cdn_enable_default() : false,
'type' => 'checkbox',
);
$options[] = array(
'name' => __('CDN 地址', 'kratos'),
'desc' => __('资源的加速前缀,例如 https://cdn.example.com。可以不带协议(自动按 https 补全)。'
. '勾选了上面的开关,这一项就必须填。', 'kratos'),
'id' => 'cdn_url',
'std' => '',
'type' => 'text',
'placeholder' => 'https://cdn.example.com',
);
/*
* 白名单的 std 就是预制清单。
*
* ⚠️ std 在运行时**完全不生效**(kratos_option 只查库),所以
* 这里只负责「后台预填」与「恢复默认」。运行时若库里没有这个键,
* 由 yang_cdn_defaults() 提供同一份内容 —— 两处必须一致,
* 否则会出现"后台显示 13 项、运行时按 0 项算"的错位。
*/
$options[] = array(
'name' => __('白名单', 'kratos'),
'desc' => __('命中这些规则的文件才走 CDN。一行一条,# 或 ; 开头的行是注释。'
. '
这里已经预填了 13 类常用静态资源,你可以直接改、加、删,保存后按你改的执行。'
. '
⚠️ 把它全部删空 = 所有静态文件都走 CDN(不只是下面这 13 类)。'
. '不想让字体、图标字体之类的走 CDN,就把 * 换成具体后缀。', 'kratos'),
'id' => 'cdn_include',
'std' => function_exists('yang_cdn_preset_text') ? yang_cdn_preset_text(yang_cdn_preset_include()) : '',
'type' => 'code',
'settings' => array('rows' => 10),
);
$options[] = array(
'name' => __('白名单写法', 'kratos'),
'desc' => __('按路径匹配(正则规则除外,它对完整地址匹配)。下面每种写法都可以直接抄:', 'kratos')
. '
* —— 全部静态文件'
. '
jpg 或 .jpg 或 *.jpg —— 扩展名'
. '
jpg,png,webp 或 .jpg .png —— 一串扩展名,命中任一'
. '
/wp-content/uploads/ —— 以这个路径开头(以斜杠开头、不含星号)'
. '
*/uploads/* —— 通配符,* 可以跨斜杠'
. '
uploads —— 路径里含这几个字(子串)'
. '
~\/20\d\d\/~ —— 正则,对完整地址匹配'
. '
扩展到字体也很常见:加一行 .woff2 .woff .ttf .eot .otf 即可。',
'type' => 'info',
);
$options[] = array(
'name' => __('黑名单', 'kratos'),
'desc' => __('命中的文件即使符合白名单也不走 CDN,保持原地址。一行一条,写法与白名单完全相同。'
. '黑名单优先于白名单:两边都命中时按黑名单处理。'
. '
这里已经预填了安全相关的后缀(.php .env .sql .bak .log 等)—— '
. '它们一旦被推到第三方 CDN 节点上,等于把配置、数据库备份、错误日志公开了。'
. '建议保留这行,即使白名单写的是 *。', 'kratos'),
'id' => 'cdn_exclude',
'std' => function_exists('yang_cdn_preset_text') ? yang_cdn_preset_text(yang_cdn_preset_exclude()) : '',
'type' => 'code',
'settings' => array('rows' => 10),
);
$options[] = array(
'name' => __('这些地址永远不走 CDN', 'kratos'),
'desc' => __('下面这些不受两套名单影响,是硬性排除 —— 把它们改到 CDN 会让站点直接坏掉,所以不给开关:'
. '
· 以斜杠结尾的地址(页面、栏目页、导航链接):改了会让访客跳去 CDN 域名,全站 404'
. '
· 页面与动态后缀:php、html、htm、asp 等'
. '
· 没有后缀的地址:通常是接口、短链、伪静态页'
. '
· 后台与接口路径:wp-admin、wp-login.php、wp-json、wp-cron.php、xmlrpc.php、/feed/'
. '
· 非本站域名:外链图片、别人家的 CDN'
. '
· 非 http(s) 协议:data:、mailto:、tel:、javascript:', 'kratos'),
'type' => 'info',
);
$options[] = array(
'name' => __('后台与接口里不改写', 'kratos'),
'desc' => __('为了不影响编辑与调试,下面这些地方保持原地址:后台页面、REST 接口、AJAX 请求、feed 订阅、WP-Cron、定制器预览、命令行。只有访客看到的前台页面才改写。', 'kratos'),
'type' => 'info',
);
/* ══════════════════════════════════════════════════════════
* 十三、自定义代码 —— 兜底用,放最后
*
* 3.2.29 起这两项默认都为空:站点自己的通用样式
* (段落缩进、h2 蓝条、列表缩进)已并入 assets/css/site.css,
* 跟着主题走、升级不丢,也不再需要在这里重复一份。
* ══════════════════════════════════════════════════════════ */
$options[] = array(
'name' => __('自定义代码', 'kratos'),
'type' => 'heading',
);
$options[] = array(
'name' => __('自定义 CSS', 'kratos'),
'desc' => __('附加样式,排在主题公共样式之后加载,用于临时覆盖。站点通用样式已并入主题的 assets/css/site.css,这里留空即可。保存后立即生效,随主题升级保留。', 'kratos'),
'id' => 'g_custom_css',
'std' => yang_opt_default_custom_css(),
'type' => 'code',
'settings' => array('rows' => 14),
);
$options[] = array(
'name' => __('自定义 JS', 'kratos'),
'desc' => __('附加脚本,在页面底部加载,不需要写 <script> 标签。', 'kratos'),
'id' => 'g_custom_js',
'std' => '',
'type' => 'code',
'settings' => array('rows' => 14),
);
return $options;
}