版本号 3.2.4 -> 3.2.5(修 Prism 报错,项目地址改为自建 Git)

## 修 Prism is not defined

首页控制台报 `Uncaught ReferenceError: Prism is not defined`,来源是
wp-editormd 插件(不是本主题):它在 Prism 脚本加载之前就无条件执行了
`Prism.plugins.autoloader.languages_path = "..."`。

线上页面里的真实顺序:
    第 668 行  该赋值语句
    第 695 行  prism-core.min.js
    第 696 行  prism-autoloader.min.js

在 `wp_head` 优先级 0 垫一个最小空壳 `window.Prism`(含 plugins.autoloader
这条访问链路),让那句赋值有地方可写。已核对 prism-core.min.js 源码:它开头
只读 `u.Prism.manual` 与 `u.Prism.disableWorkerMessageHandler`,结尾
`global.Prism = Prism` 整体覆盖 —— 空壳必定被真实对象替换,不承担持久职责,
只为吸收那条过早的赋值。已用 jsdom 验证:去掉空壳重现原始报错,加上后消失,
且之后 `Prism.highlightAll` 仍可正常调用。

## 项目地址统一到 code.yangyq.net

原作者署名、原主题地址、README、语言包、JS 里的控制台横幅全部换成自建仓库地址。
LICENSE 文件保持原样不动(MIT 要求保留原始版权声明)。

## CDN 分支改成拿不到就回退本地

原来的 `g_cdn` 分支指向 `cdn.jsdelivr.net/gh/vtrois/kratos`,本仓库在自建
Gitea 上,jsDelivr 只认 github/npm/wordpress,实测该地址 404。现改为仅在
`YANG_THEME_CDN_REPO` 常量存在时才走 CDN,否则一律用
`get_template_directory_uri()`。留一个 404 的地址比留空更危险:页面能开、
样式全丢,极难排查。

## 顺带

- `.gitattributes` 补 `*.mo binary`:原来是靠"含 NUL"启发式判定,不是契约
- `update.json` 的版本号跟进到 3.2.5
- `kratos.min.js` / `kratos.min.css` 用压缩器重新生成,不手工改产物
This commit is contained in:
2026-10-23 12:55:41 +08:00
parent b36f4b184a
commit 4f0d19fb91
32 changed files with 120 additions and 60 deletions
+60 -3
View File
@@ -1,13 +1,23 @@
<?php
/**
* 核心函数
* @author Seaton Jiang <seaton@vtrois.com>
* @author Yongquan Yang <yangyq.net>
* @license MIT License
* @version 2020.08.04
*/
if (kratos_option('g_cdn', false)) {
$asset_path = 'https://cdn.jsdelivr.net/gh/vtrois/kratos@' . THEME_VERSION;
// CDN 资源分支。
//
// ⚠️ 这里的地址必须是**能被 jsDelivr 拉取的 GitHub 仓库**(jsDelivr 只认
// github / npm / wordpress 等白名单源,不支持自建 Gitea/GitLab)。
// 本项目的主仓库在 https://code.yangyq.net/laoyang/wordpress-kratos-yang,
// 它**不能**直出给 jsDelivr(实测 404)。
// 因此:
// · 线上 g_cdn 选项默认关闭,走 get_template_directory_uri() 本地资源;
// · 若将来要启用 CDN,必须先把仓库镜像到 GitHub,再把下面的 owner/repo 换成镜像地址。
// 留一个 404 的地址比留空更危险:页面能打开、样式却全丢,排查成本极高。
if (kratos_option('g_cdn', false) && defined('YANG_THEME_CDN_REPO')) {
$asset_path = 'https://cdn.jsdelivr.net/gh/' . YANG_THEME_CDN_REPO . '@' . THEME_VERSION;
} else {
$asset_path = get_template_directory_uri();
}
@@ -96,6 +106,53 @@ function theme_autoload()
}
add_action('wp_enqueue_scripts', 'theme_autoload');
/**
* Prism 前置兜底(修 Uncaught ReferenceError: Prism is not defined)
*
* 病因在 wp-editormd 插件,不在本主题。实测线上页面顺序:
* 668 行 Prism.plugins.autoloader.languages_path = "..."; ← 无条件赋值
* 695 行 <script src="prism-core.min.js">
* 696 行 <script src="prism-autoloader.min.js">
* 赋值语句在 Prism 加载**之前**执行 ⇒ 抛 ReferenceError,且这条赋值实际上
* 也完全没生效(真正的 languages_path 靠 footer.php 里那段带 if 防护的兜底设置)。
*
* 插件自己在页尾另一处写了 `if (window.Prism && ...)`,说明是它自己没改干净。
*
* 修法:在 <head> 极早位置(wp_head 优先级 0)先垫一个空壳 window.Prism,
* 把 plugins.autoloader 这条访问链路铺好,让插件那句赋值有地方可写,不再抛错。
*
* 关于「会不会被真实 Prism 冲掉」——已核对 prism-core.min.js 源码:
* 开头 `C={manual: u.Prism && u.Prism.manual, ...}` 只读取 manual /
* disableWorkerMessageHandler 两个开关;结尾 `global.Prism = Prism` 整体覆盖。
* 也就是说空壳对象**确实会被替换**,autoloader 也是随后由
* prism-autoloader.min.js 重新挂到新对象上的。
* 所以这里垫的对象只负责「让第 668 行不报错」,不承担持久职责 —— 正合适。
* 为避免误导后来人,这里刻意只做最小空壳,不塞任何逻辑。
*
* 用 var 而非 window.Prism= 是为了在严格模式下也能安全创建全局;
* 且仅在尚未存在时才创建,插件/主题自己先初始化时本段什么都不做。
*/
function yang_prism_early_shim()
{
if (is_admin()) {
return;
}
// 注意:这里是给浏览器执行的 JS,不是 PHP 字符串拼接出错也无妨,
// 但保持单行数组 + implode,避免 HEREDOC 里出现 <? 之类被误解析。
$lines = array(
"if (typeof window.Prism === 'undefined') {",
"\twindow.Prism = {};",
"\twindow.Prism.plugins = {};",
"\twindow.Prism.plugins.autoloader = {};",
"\twindow.Prism.plugins.autoloader.languages_path = '';",
"}",
);
echo '<script id="yang-prism-shim">' . "\n"
. implode("\n", $lines) . "\n"
. '</script>' . "\n";
}
add_action('wp_head', 'yang_prism_early_shim', 0);
// Admin Bar
if (! kratos_option('g_adminbar', true)) {
add_filter('show_admin_bar', '__return_false');