{"id":1257,"date":"2025-10-15T19:09:30","date_gmt":"2025-10-15T11:09:30","guid":{"rendered":"https:\/\/www.myclass-lin.org\/wordpress\/?p=1257"},"modified":"2025-10-15T23:24:39","modified_gmt":"2025-10-15T15:24:39","slug":"%f0%9f%a7%a9-prism-smart-lite-%e5%a4%96%e6%8e%9b%e8%aa%aa%e6%98%8e%e6%96%87%e4%bb%b6","status":"publish","type":"post","link":"https:\/\/www.myclass-lin.org\/wordpress\/archives\/1257","title":{"rendered":"\ud83e\udde9 Prism Smart Lite \u5916\u639b\u8aaa\u660e\u6587\u4ef6"},"content":{"rendered":"<p>Prism Smart Lite \u662f\u4e00\u6b3e\u70ba WordPress \u6253\u9020\u7684\u8f15\u91cf\u7a0b\u5f0f\u78bc\u9ad8\u4eae\u5916\u639b\uff0c\u652f\u63f4\u524d\u53f0\u4eae\/\u6697\u4e3b\u984c\u5207\u63db\u3001\u884c\u865f\u3001\u5de5\u5177\u5217\uff08\u6a94\u540d\u3001\u8907\u88fd\u3001\u6536\u5408\u3001\u63db\u884c\uff09\u3001\u77ed\u4ee3\u78bc &#8216;[&#8216;codeplaceholder&#8217;]&#8217; \u8207 &#8216;[&#8216;codefile&#8217;]&#8217;\uff0c\u4e26\u5177\u5099\u6a94\u6848\u4e0a\u50b3\u3001\u8cc7\u6599\u593e\u7ba1\u7406\u3001\u63cf\u8ff0\u7dad\u8b77\u8207 .htaccess \u5b89\u5168\u4fdd\u8b77\u529f\u80fd\u3002\u5f8c\u53f0\u53ef\u8a2d\u5b9a\u986f\u793a\u8207\u9032\u968e\u9078\u9805\u3001\u6a39\u72c0\u6a94\u6848\u7ba1\u7406\u8207\u8def\u5f91\u6e2c\u8a66\uff0c\u7121\u9700\u65b0\u589e\u8cc7\u6599\u8868\u3002\u9069\u7528 WordPress 5.8+\u3001PHP 7.4+\u3002<\/p>\n<p><!--more--><\/p>\n<article class=\"summary-post\" lang=\"zh-Hant\">\n<h1>\ud83e\udde9 Prism Smart Lite \u5916\u639b\u8aaa\u660e\u6587\u4ef6<\/h1>\n<h2>\u4e00\u3001\u5916\u639b\u6982\u8ff0<\/h2>\n<p><strong>Prism Smart Lite<\/strong> \u662f\u4e00\u6b3e\u70ba WordPress \u6240\u8a2d\u8a08\u7684\u7cbe\u7c21\u7a0b\u5f0f\u78bc\u9ad8\u4eae\u5916\u639b\uff0c\u652f\u63f4\uff1a\u524d\u53f0\u7a0b\u5f0f\u78bc\u9ad8\u4eae\uff08\u4eae\/\u6697\u4e3b\u984c\uff09\u3001\u884c\u865f\u3001\u5de5\u5177\u5217\uff08\u6a94\u540d\/\u8907\u88fd\/\u6536\u5408\/\u63db\u884c\u5207\u63db\uff09\u3001\u77ed\u4ee3\u78bc <code>'['codeplaceholder']'<\/code> \u8207 <code>'['codefile']'<\/code>\u3001\u6a94\u6848\u4e0a\u50b3\u8207\u8cc7\u6599\u593e\u7ba1\u7406\u3001\u6a94\u6848\u63cf\u8ff0\u8a18\u9304\u8207\u5b89\u5168\u4fdd\u8b77\uff08.htaccess\uff09\u3002<\/p>\n<hr \/>\n<h2>\u4e8c\u3001\u4e3b\u8981\u529f\u80fd\u5f59\u6574<\/h2>\n<h3>\ud83d\udd39 \u524d\u53f0\u986f\u793a\u529f\u80fd<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u529f\u80fd<\/th>\n<th>\u8aaa\u660e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u77ed\u4ee3\u78bc &#8216;[&#8216;codeplaceholder&#8217;]&#8217;<\/td>\n<td>\u5728\u6587\u7ae0\u4e2d\u76f4\u63a5\u986f\u793a\u8cbc\u4e0a\u7684\u539f\u59cb\u7a0b\u5f0f\u78bc\uff08\u5167\u5bb9\u539f\u6a23\u4fdd\u7559\uff0c\u907f\u514d WP \u6539\u5beb\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u77ed\u4ee3\u78bc &#8216;[&#8216;codefile&#8217;]&#8217;<\/td>\n<td>\u5f9e\u4e0a\u50b3\u7684\u6a94\u6848\u8f09\u5165\u4e26\u986f\u793a\u7a0b\u5f0f\u78bc\uff08\u9810\u8a2d\u8cc7\u6599\u593e <code>\/uploads\/code-snippets\/<\/code>\uff1b\u53ef\u8a2d\u767d\u540d\u55ae\u8def\u5f91\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u4eae \/ \u6697\u4e3b\u984c\u5207\u63db<\/td>\n<td>\u8a2d\u5b9a\u4e2d\u5207\u63db\uff0c\u524d\u53f0\u81ea\u52d5\u5957\u7528 Prism \u4e3b\u984c\uff08Okaidia \/ Default\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u884c\u865f\u986f\u793a<\/td>\n<td>\u53ef\u5168\u57df\u958b\u555f\u6216\u5728\u55ae\u4e00\u77ed\u4ee3\u78bc\u8986\u5beb\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u5de5\u5177\u5217<\/td>\n<td>\u6a94\u540d\u5fbd\u7ae0\u3001\u8907\u88fd\u3001\u6536\u5408\u3001\u63db\u884c\u5207\u63db\u7b49\u6309\u9215\u53ef\u7368\u7acb\u555f\u7528\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u6536\u5408 \/ \u5c55\u958b<\/td>\n<td>\u53ef\u8a2d\u5b9a\u9810\u8a2d\u70ba\u6536\u5408\u6216\u5c55\u958b\uff0c\u672a\u5c55\u958b\u7684\u6700\u5927\u9ad8\u5ea6\u53ef\u81ea\u8a02\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u5bec \/ \u9ad8\u63a7\u5236<\/td>\n<td>\u53ef\u81ea\u8a02\u6700\u5927\u5bec\u5ea6\u8207\u672a\u6536\u5408\u6700\u5927\u9ad8\u5ea6\uff0c\u907f\u514d\u7834\u7248\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u63db\u884c\u63a7\u5236<\/td>\n<td>\u53ef\u5207\u63db\u55ae\u884c\u6a6b\u5411\u6372\u52d5\u8207\u81ea\u52d5\u6298\u884c\u3002<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\ud83d\udd39 \u5f8c\u53f0\u7ba1\u7406\u529f\u80fd<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u529f\u80fd<\/th>\n<th>\u8aaa\u660e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u986f\u793a\u8a2d\u5b9a<\/td>\n<td>\u4e3b\u984c\u3001\u9810\u8a2d\u6536\u5408\u3001\u6700\u5927\u5bec\u5ea6\/\u9ad8\u5ea6\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u9032\u968e\u8a2d\u5b9a<\/td>\n<td>\u8cc7\u6e90\u8f09\u5165\u6a21\u5f0f\u3001\u884c\u865f\u3001\u5de5\u5177\u5217\u3001\u5141\u8a31\u526f\u6a94\u540d\u3001\u767d\u540d\u55ae\u8def\u5f91\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u6a94\u6848\u7ba1\u7406<\/td>\n<td>\u6a39\u72c0\u7d50\u69cb\u700f\u89bd\u8cc7\u6599\u593e\u8207\u6a94\u6848\u3001\u4f9d\u8cc7\u6599\u593e\u7be9\u9078\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u4e0a\u50b3\u6a94\u6848<\/td>\n<td>\u53ef\u4e0a\u50b3\u81f3\u76ee\u524d\u9078\u53d6\u7684\u8cc7\u6599\u593e\uff0c\u4e26\u540c\u6642\u586b\u5beb\u63cf\u8ff0\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u63cf\u8ff0\u7ba1\u7406<\/td>\n<td>\u6bcf\u6a94\u53ef\u55ae\u7368\u7de8\u8f2f\u63cf\u8ff0\uff08\u5132\u65bc <code>.psl_meta.json<\/code>\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u5efa\u7acb\u8cc7\u6599\u593e<\/td>\n<td>\u65bc\u76ee\u524d\u76ee\u9304\u65b0\u589e\u5b50\u8cc7\u6599\u593e\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u522a\u9664\u8cc7\u6599\u593e<\/td>\n<td>\u53ef\u522a\u7a7a\u8cc7\u6599\u593e\u6216\u905e\u8ff4\u522a\u9664\u6574\u500b\u8cc7\u6599\u593e\uff08\u540c\u6b65\u6e05\u7406\u63cf\u8ff0\u8a18\u9304\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u522a\u9664\u6a94\u6848<\/td>\n<td>\u53ef\u55ae\u4e00\u522a\u9664\u6a94\u6848\uff0c\u63cf\u8ff0\u540c\u6b65\u79fb\u9664\u3002<\/td>\n<\/tr>\n<tr>\n<td>.htaccess \u7ba1\u7406<\/td>\n<td>\u4e00\u9375\u751f\u6210\/\u522a\u9664\uff0c\u9810\u8a2d\u5c01\u9396 PHP \u57f7\u884c\u8207\u7d22\u5f15\u3002<\/td>\n<\/tr>\n<tr>\n<td>\u8def\u5f91\u6e2c\u8a66<\/td>\n<td>\u986f\u793a\u4f3a\u670d\u5668\u5be6\u969b\u8def\u5f91\uff0c\u5229\u65bc\u9664\u932f\u3002<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>\u4e09\u3001\u5b89\u88dd\u65b9\u5f0f<\/h2>\n<ol>\n<li>\u5c07\u5916\u639b\u8cc7\u6599\u593e <code>prism-smart-lite<\/code> \u653e\u5165 <code>\/wp-content\/plugins\/<\/code>\u3002<\/li>\n<li>\u767b\u5165 WordPress \u2192 \u5916\u639b \u2192 \u555f\u7528 Prism Smart Lite\u3002<\/li>\n<li>\u555f\u7528\u5f8c\u7cfb\u7d71\u6703\u81ea\u52d5\u5efa\u7acb <code>\/wp-content\/uploads\/code-snippets\/<\/code> \u76ee\u9304\u3002<\/li>\n<\/ol>\n<hr \/>\n<h2>\u56db\u3001\u4f7f\u7528\u6d41\u7a0b<\/h2>\n<h3>\u2705 \u5f8c\u53f0\u8a2d\u5b9a<\/h3>\n<ul>\n<li>\u9032\u5165\u300c\u8a2d\u5b9a \u2192 Prism Smart Lite\u300d\u3002<\/li>\n<li>\u5728\u300c\u986f\u793a\u8a2d\u5b9a\u300d\u9078\u4e3b\u984c\u3001\u9810\u8a2d\u6536\u5408\u3001\u5bec\u9ad8\u3002<\/li>\n<li>\u5728\u300c\u9032\u968e\u8a2d\u5b9a\u300d\u8abf\u6574\u8f09\u5165\u6a21\u5f0f\u3001\u884c\u865f\u3001\u5de5\u5177\u5217\u3001\u5141\u8a31\u526f\u6a94\u540d\u8207\u767d\u540d\u55ae\u8def\u5f91\u3002<\/li>\n<\/ul>\n<h3>\u2705 \u7ba1\u7406\u6a94\u6848<\/h3>\n<ul>\n<li>\u5de6\u5074\u6a39\u72c0\u6e05\u55ae\u9078\u8cc7\u6599\u593e \u2192 \u53f3\u5074\u53ef\u4e0a\u50b3\u3001\u7de8\u8f2f\u63cf\u8ff0\u3001\u522a\u9664\u6a94\u6848\u3002<\/li>\n<li>\u53ef\u5efa\u7acb \/ \u522a\u9664\u8cc7\u6599\u593e\uff08\u905e\u8ff4\u522a\u9664\u5c07\u6e05\u7a7a\u6240\u6709\u5167\u5bb9\u8207\u63cf\u8ff0\uff09\u3002<\/li>\n<li>\u5efa\u8b70\u751f\u6210 <code>.htaccess<\/code> \u63d0\u5347\u5b89\u5168\u3002<\/li>\n<\/ul>\n<h3>\u2705 \u524d\u53f0\u4f7f\u7528\u77ed\u4ee3\u78bc<\/h3>\n<p>\u76f4\u63a5\u8cbc\u4e0a\u7a0b\u5f0f\u78bc\uff1a<\/p>\n<blockquote><p>&#8216;[&#8216;codeplaceholder lang=&#8221;php&#8221; file=&#8221;test.php&#8221; collapsed=&#8221;0&#8243;&#8216;]&#8217;<br \/>\n&lt;?php echo &#8220;Hello World!&#8221;; ?&gt;<br \/>\n&#8216;[&#8216;\/codeplaceholder&#8217;]&#8217;<\/p><\/blockquote>\n<p>\u986f\u793a\u4e0a\u50b3\u6a94\u6848\uff1a<\/p>\n<blockquote><p>&#8216;[&#8216;codefile src=&#8221;utils\/demo.js&#8221; collapsed=&#8221;1&#8243; linenumbers=&#8221;1&#8243;]'[&#8216;\/codefile&#8217;]&#8217;<\/p><\/blockquote>\n<hr \/>\n<h2>\u4e94\u3001\u8cc7\u6599\u5132\u5b58\u7d50\u69cb<\/h2>\n<ul>\n<li><strong>\u4e0a\u50b3\u6a94\u6848\uff1a<\/strong> <code>\/wp-content\/uploads\/code-snippets\/<\/code><\/li>\n<li><strong>\u6a94\u6848\u63cf\u8ff0\uff1a<\/strong> <code>\/wp-content\/uploads\/code-snippets\/.psl_meta.json<\/code><\/li>\n<li><strong>\u5916\u639b\u8a2d\u5b9a\uff1a<\/strong> \u8cc7\u6599\u5eab <code>wp_options<\/code> \u8868\uff08<code>option_name=psl_options<\/code>\uff09<\/li>\n<li><strong>\u5b89\u5168\u8a2d\u5b9a\uff1a<\/strong> <code>\/wp-content\/uploads\/code-snippets\/.htaccess<\/code><\/li>\n<\/ul>\n<hr \/>\n<h2>\u516d\u3001\u6ce8\u610f\u4e8b\u9805<\/h2>\n<ul>\n<li>\u5728\u672a\u5efa\u7acb <code>.htaccess<\/code> \u524d\uff0c\u8acb\u52ff\u4e0a\u50b3\u53ef\u57f7\u884c\u7684 PHP \u6a94\u81f3\u8a72\u8cc7\u6599\u593e\u3002<\/li>\n<li>\u905e\u8ff4\u522a\u9664\u8cc7\u6599\u593e\u6703\u6c38\u4e45\u79fb\u9664\u6240\u6709\u5167\u5bb9\uff0c\u8acb\u5148\u5099\u4efd\u3002<\/li>\n<li>\u9810\u8a2d\u5141\u8a31\u526f\u6a94\u540d\uff1a<code>php,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx<\/code>\uff08\u53ef\u65bc\u9032\u968e\u8a2d\u5b9a\u8abf\u6574\uff09\u3002<\/li>\n<li>\u82e5\u9700\u986f\u793a\u975e\u4e0a\u50b3\u76ee\u9304\u7684\u6a94\u6848\uff0c\u8acb\u5728\u300c\u767d\u540d\u55ae\u8def\u5f91\u300d\u52a0\u5165\u8a72\u8cc7\u6599\u593e\u7d55\u5c0d\u8def\u5f91\u3002<\/li>\n<\/ul>\n<hr \/>\n<h2>\u4e03\u3001\u88dc\u5145\u8aaa\u660e<\/h2>\n<p><strong>.psl_meta.json<\/strong> \u7531\u5916\u639b\u81ea\u52d5\u7dad\u8b77\uff1b\u4e0a\u50b3\/\u522a\u9664\/\u4fee\u6539\u63cf\u8ff0\u7686\u6703\u540c\u6b65\u66f4\u65b0\u3002<\/p>\n<p><strong>.htaccess<\/strong> \u9810\u8a2d\u5167\u5bb9\uff1a<\/p>\n<blockquote><p>Options -Indexes<br \/>\n&lt;FilesMatch &#8220;\\.(php|phtml|phar)$&#8221;&gt;<br \/>\nRequire all denied<br \/>\n&lt;\/FilesMatch&gt;<\/p><\/blockquote>\n<p><strong>\u5099\u4efd\u5efa\u8b70\uff1a<\/strong> \u5099\u4efd\u6574\u500b <code>\/uploads\/code-snippets\/<\/code>\uff08\u542b <code>.psl_meta.json<\/code>\u3001<code>.htaccess<\/code>\uff09\uff0c\u518d\u5099\u4efd\u8cc7\u6599\u5eab\u7684 <code>psl_options<\/code>\u3002<\/p>\n<hr \/>\n<h2>\u516b\u3001\u9069\u7528\u74b0\u5883<\/h2>\n<ul>\n<li>WordPress 5.8+<\/li>\n<li>PHP 7.4+<\/li>\n<li>\u4e0d\u9700\u984d\u5916\u8cc7\u6599\u8868\uff0c\u652f\u63f4\u5feb\u53d6\u5916\u639b\u3002<\/li>\n<\/ul>\n<hr \/>\n<h2>\u4e5d\u3001\u7bc4\u4f8b\u61c9\u7528<\/h2>\n<p>\u986f\u793a PHP \u51fd\u5f0f\uff1a<\/p>\n<blockquote><p>&#8216;[&#8216;codeplaceholder lang=&#8221;php&#8221; file=&#8221;functions.php&#8221;]<br \/>\nfunction add($a, $b){ return $a + $b; }<br \/>\n&#8216;[&#8216;\/codeplaceholder&#8217;]&#8217;<\/p><\/blockquote>\n<p>\u986f\u793a\u4e0a\u50b3\u7684 JS \u6a94\uff1a<\/p>\n<blockquote><p>&#8216;[&#8216;codefile src=&#8221;scripts\/app.js&#8221; linenumbers=&#8221;1&#8243; collapsed=&#8221;1&#8243;]'[&#8216;\/codefile&#8217;]&#8217;<\/p><\/blockquote>\n<p>\u986f\u793a YAML \/ JSON\uff1a<\/p>\n<blockquote><p>&#8216;[&#8216;codeplaceholder lang=&#8221;yaml&#8221; file=&#8221;ci.yml&#8221;]<br \/>\nname: build<br \/>\non: [push]<br \/>\njobs: { build: { runs-on: ubuntu-latest } }<br \/>\n&#8216;[&#8216;\/codeplaceholder&#8221;]&#8217;<\/p><\/blockquote>\n<hr \/>\n<h2>\u5341\u3001\u7248\u672c\u8cc7\u8a0a<\/h2>\n<table>\n<thead>\n<tr>\n<th>\u7248\u672c<\/th>\n<th>\u65e5\u671f<\/th>\n<th>\u66f4\u65b0\u5167\u5bb9<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>v1.1.0<\/td>\n<td>2025-10<\/td>\n<td>\u9032\u968e\u8a2d\u5b9a\u3001\u8cc7\u6599\u593e\u522a\u9664\uff08\u542b\u905e\u8ff4\uff09\u3001\u6a39\u72c0\u700f\u89bd\u3001\u63cf\u8ff0\u7dad\u8b77\u3001.htaccess \u7ba1\u7406\uff1b\u77ed\u4ee3\u78bc\u5167\u5bb9\u5b8c\u6574\u4fdd\u7559\uff1b\u55ae\u4e00\u9801\u8a2d\u5b9a\u6574\u5408\uff1b\u63d0\u793a\u8a0a\u606f\u9632\u91cd\u8907\u3002<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>\u5341\u4e00\u3001\u6a94\u6848\u539f\u59cb\u78bc<\/h2>\n<h1>prism-smart-lite.php<\/h1>\n<div class=\"psl-wrap\"><pre class=\"psl-pre line-numbers\" data-collapsed=\"1\"><code class=\"language-php\" data-file=\"prism-smart-lite.php\">&lt;?php\n\/**\n * Plugin Name: Prism Smart Lite\n * Description: \u7cbe\u7c21\u7248\u7a0b\u5f0f\u78bc\u9ad8\u4eae\u5916\u639b\uff1a\u884c\u865f\u3001\u53f3\u4e0a\u5de5\u5177\u5217\uff08\u6a94\u540d\/\u8907\u88fd\/\u6536\u5408\/\u63db\u884c\u5207\u63db\uff09\u3001\u4eae\/\u6697\u4e3b\u984c\u3002\u63d0\u4f9b [codeplaceholder] \u8207 [codefile]\uff1b\u542b\u5bec\u5ea6\u8207\u9ad8\u5ea6\u4e0a\u9650\u8a2d\u5b9a\uff0c\u907f\u514d\u7834\u7248\u3002v1.1.0\uff1a\u77ed\u4ee3\u78bc\u5167\u5bb9\u539f\u6a23\u4fdd\u7559\uff08\u4e0d\u88ab WordPress \u4fee\u6539\uff09\uff0c\u4e26\u652f\u63f4\u767d\u540d\u55ae\u6a94\u6848\u8b80\u53d6\u3002\n * Version: 1.1.1\n * Author: Lin\n * License: GPL-2.0+\n *\/\nif (!defined('ABSPATH')) exit;\n\nclass Prism_Smart_Lite {\n    const OPT_KEY = 'psl_options';\n    private static $instance = null;\n\n    public static function init(){\n        if(!self::$instance) self::$instance = new self();\n        return self::$instance;\n    }\n\n    private function __construct(){\n        register_activation_hook(__FILE__, [$this,'on_activate']);\n        add_action('wp_enqueue_scripts', [$this,'enqueue_assets']);\n        add_shortcode('codeplaceholder', [$this,'shortcode_codeplaceholder']);\n        add_shortcode('codebox',        [$this,'shortcode_codeplaceholder']); \/\/ \u5225\u540d\n        add_shortcode('codefile',       [$this,'shortcode_codefile']);        \/\/ \u5916\u90e8\u6a94\u6848\u8b80\u53d6\n    }\n\n    \/** \u9810\u8a2d\u503c\uff1a\u7dad\u6301\u76f8\u5bb9 + \u65b0\u589e\u53ef\u9078\u8a2d\u5b9a *\/\n    private function defaults(){\n        return [\n            'theme'         =&gt; 'light', \/\/ light|dark\uff08\u7dad\u6301\u4f60\u539f\u672c\u5169\u7a2e\uff09\n            'collapsed'     =&gt; '0',     \/\/ 0|1 \u9810\u8a2d\u662f\u5426\u6536\u5408\n            'max_width'     =&gt; '100%',\n            'max_height'    =&gt; '70vh',\n            \/\/ \u65b0\u589e\n            'enqueue_mode'  =&gt; 'all',   \/\/ all|shortcode\n            'line_numbers'  =&gt; 1,       \/\/ 1|0\n            'show_filename' =&gt; 1,       \/\/ 1|0\n            'enable_copy'   =&gt; 1,       \/\/ 1|0\n            'enable_collapse'    =&gt; 1,  \/\/ 1|0\n            'enable_wrap_toggle' =&gt; 0,  \/\/ 1|0\n            'allow_mimes'   =&gt; 'php,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx',\n            'allowed_paths' =&gt; [],      \/\/ \u8def\u5f91\u767d\u540d\u55ae\uff08\u9663\u5217\uff09\n        ];\n    }\n\n    private function opt($key=null, $fallback=null){\n        $opt = wp_parse_args(get_option(self::OPT_KEY, []), $this-&gt;defaults());\n        return $key===null ? $opt : (isset($opt[$key]) ? $opt[$key] : $fallback);\n    }\n\n    public function on_activate(){\n        $defaults = $this-&gt;defaults();\n        $opt = get_option(self::OPT_KEY);\n        update_option(self::OPT_KEY, is_array($opt) ? array_merge($defaults,$opt) : $defaults);\n\n        \/\/ \u5efa\u7acb uploads\/code-snippets\uff08\u76f8\u5bb9\u820a\u884c\u70ba\uff09\n        $uploads  = wp_upload_dir();\n        $snip_dir = trailingslashit($uploads['basedir']) . 'code-snippets';\n        if (!is_dir($snip_dir)) {\n            wp_mkdir_p($snip_dir);\n        }\n    }\n\n    \/** CDN \u8cc7\u6e90\u8868 *\/\n    private function get_assets(){\n        $theme = $this-&gt;opt('theme', 'light');\n        return [\n            'css'      =&gt; $theme==='dark'\n                ? 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/themes\/prism-okaidia.min.css'\n                : 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/themes\/prism.min.css',\n            'line_css' =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/line-numbers\/prism-line-numbers.min.css',\n            'tb_css'   =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/toolbar\/prism-toolbar.min.css',\n            'core'     =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/components\/prism-core.min.js',\n            'auto'     =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/autoloader\/prism-autoloader.min.js',\n            'line'     =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/line-numbers\/prism-line-numbers.min.js',\n            'tb'       =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/toolbar\/prism-toolbar.min.js',\n            'copy'     =&gt; 'https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/plugins\/copy-to-clipboard\/prism-copy-to-clipboard.min.js',\n        ];\n    }\n\n    \/** \u672c\u9801\u662f\u5426\u542b\u77ed\u4ee3\u78bc\uff08\u4f9b enqueue_mode=shortcode \u7528\uff09 *\/\n    private function has_shortcode_on_page() {\n        if (is_admin()) return false;\n        $types = ['codeplaceholder','codebox','codefile'];\n        \/\/ \u55ae\u7bc7\n        global $post;\n        if ($post && !empty($post-&gt;post_content)) {\n            foreach ($types as $t) if (has_shortcode($post-&gt;post_content, $t)) return true;\n        }\n        \/\/ \u5c0f\u5de5\u5177\/\u5340\u584a\u7b49\uff08\u7c21\u6613\u5075\u6e2c\uff09\n        $buf = get_the_content(null, false, $post);\n        if ($buf) {\n            foreach ($types as $t) if (strpos($buf, \"[$t\") !== false) return true;\n        }\n        return false;\n    }\n\n    \/** \u524d\u7aef\u8f09\u5165 *\/\n    public function enqueue_assets(){\n        $mode = $this-&gt;opt('enqueue_mode', 'all'); \/\/ all|shortcode\n        if ($mode === 'shortcode' && !$this-&gt;has_shortcode_on_page()) return;\n\n        $u = $this-&gt;get_assets();\n        wp_enqueue_style('psl-theme',   $u['css'], [], '1.0');\n        wp_enqueue_style('psl-linecss', $u['line_css'], [], '1.0');\n        wp_enqueue_style('psl-tbcss',   $u['tb_css'], [], '1.0');\n\n        wp_enqueue_script('psl-core', $u['core'], [], '1.0', true);\n        wp_enqueue_script('psl-auto', $u['auto'], ['psl-core'], '1.0', true);\n        wp_enqueue_script('psl-line', $u['line'], ['psl-core'], '1.0', true);\n        wp_enqueue_script('psl-tb',   $u['tb'],   ['psl-core'], '1.0', true);\n\n        if ($this-&gt;opt('enable_copy',1)) {\n            wp_enqueue_script('psl-copy', $u['copy'], ['psl-tb'], '1.0', true);\n        }\n\n        wp_add_inline_script('psl-auto','Prism.plugins.autoloader.languages_path=\"https:\/\/cdn.jsdelivr.net\/npm\/prismjs@1\/components\/\";','before');\n\n        \/\/ CSS\uff1a\u5bec\/\u9ad8\uff08\u5f8c\u53f0\u53ef\u8abf\uff09\n        $max_w = trim($this-&gt;opt('max_width','100%'));\n        $max_h = trim($this-&gt;opt('max_height','70vh'));\n        $css = &lt;&lt;&lt;CSS\n.psl-wrap{\n  position:relative;\n  max-width: {$max_w};\n  width:100%;\n  overflow:hidden;\n  margin-left:auto;margin-right:auto;\n}\npre.psl-pre{\n  margin:1.25rem 0;\n  border-radius:10px;\n  max-width:100%;\n  box-sizing:border-box;\n  overflow:auto;\n  white-space:pre; \/* \u4e0d\u81ea\u52d5\u63db\u884c *\/\n}\npre.psl-pre.line-numbers{position:relative;padding-left:3.8em;}\npre.psl-pre code{display:block;white-space:pre;word-break:normal;overflow-wrap:normal;}\npre.psl-pre:not(.collapsed){max-height: {$max_h};}\npre.psl-pre.collapsed{max-height:140px;overflow:hidden;position:relative;}\npre.psl-pre.collapsed::after{\n  content:'';position:absolute;left:0;right:0;bottom:0;height:48px;\n  background:linear-gradient(transparent,rgba(0,0,0,.08));pointer-events:none;\n}\n\/* Toolbar \u5fae\u8abf *\/\n.psl-filename{padding:0 10px;opacity:.8;font-size:12px;}\ndiv.code-toolbar&gt;.toolbar{gap:6px;}\n.line-numbers .line-numbers-rows{box-sizing:content-box;}\n\/* \u81ea\u52d5\u63db\u884c\u6a21\u5f0f\uff08\u7531\u6309\u9215\u5207\u63db\u6642\u639b\u4e0a .wrap-lines\uff09 *\/\npre.psl-pre.wrap-lines code{white-space:pre-wrap;word-break:break-word;}\nCSS;\n        wp_add_inline_style('psl-theme', $css);\n\n        \/\/ \u5de5\u5177\u5217\u6309\u9215\uff08\u4f9d\u8a2d\u5b9a\u52d5\u614b\u8a3b\u518a\uff09\n        $enable_filename = $this-&gt;opt('show_filename',1) ? 'true' : 'false';\n        $enable_collapse = $this-&gt;opt('enable_collapse',1) ? 'true' : 'false';\n        $enable_wrap     = $this-&gt;opt('enable_wrap_toggle',0) ? 'true' : 'false';\n        $collapsed_def   = !empty($this-&gt;opt('collapsed','0')) ? '1' : '0';\n        $line_numbers_on = $this-&gt;opt('line_numbers',1) ? 'true' : 'false';\n\n        $js = &lt;&lt;&lt;JS\n(function(){\n  function ensureLineNumbers(){\n    if ($line_numbers_on) {\n      document.querySelectorAll('pre.psl-pre').forEach(function(pre){\n        pre.classList.add('line-numbers');\n      });\n    } else {\n      document.querySelectorAll('pre.psl-pre').forEach(function(pre){\n        pre.classList.remove('line-numbers');\n      });\n    }\n  }\n\n  if (Prism && Prism.plugins && Prism.plugins.toolbar){\n    if ($enable_filename) {\n      Prism.plugins.toolbar.registerButton('psl-filename', function(env){\n        var f = env.element.getAttribute('data-file'); if(!f) return;\n        var s = document.createElement('span'); s.className='psl-filename'; s.textContent=f; return s;\n      });\n    }\n    if ($enable_collapse) {\n      Prism.plugins.toolbar.registerButton('psl-collapse', function(env){\n        var b=document.createElement('button'); b.textContent='\u6536\u5408';\n        b.addEventListener('click', function(){\n          var pre = env.element.closest('pre'); if(!pre) return;\n          pre.classList.toggle('collapsed');\n          b.textContent = pre.classList.contains('collapsed') ? '\u5c55\u958b' : '\u6536\u5408';\n        });\n        return b;\n      });\n    }\n    if ($enable_wrap) {\n      Prism.plugins.toolbar.registerButton('psl-wrap', function(env){\n        var btn=document.createElement('button'); btn.textContent='\u63db\u884c';\n        btn.addEventListener('click', function(){\n          var pre = env.element.closest('pre'); if(!pre) return;\n          pre.classList.toggle('wrap-lines'); \/\/ \u5207\u63db CSS white-space\n        });\n        return btn;\n      });\n    }\n  }\n\n  document.addEventListener('DOMContentLoaded', function(){\n    ensureLineNumbers();\n    var def = ('{$collapsed_def}' === '1');\n    document.querySelectorAll('pre.psl-pre').forEach(function(pre){\n      if(pre.getAttribute('data-collapsed')==='1' || def) pre.classList.add('collapsed');\n    });\n  });\n})();\nJS;\n        wp_add_inline_script('psl-tb', $js, 'after');\n    }\n\n    \/** \u5167\u6587\u77ed\u4ee3\u78bc\uff1a\u4fdd\u7559\u539f\u6587\u8f38\u51fa\uff08\u4f60\u7684\u4f5c\u6cd5\uff09 *\/\n    public function shortcode_codeplaceholder($atts, $content=null){\n        $collapsed_default = !empty($this-&gt;opt('collapsed','0')) ? '1' : '0';\n        $a = shortcode_atts([\n            'file'      =&gt; 'snippet.txt',\n            'lang'      =&gt; 'markup',\n            'collapsed' =&gt; '',\n            'linenumbers' =&gt; '', \/\/ \u53ef\u7528\u65bc\u55ae\u584a\u8986\u5beb\u884c\u865f\uff1a1\/0\n        ], $atts, 'codeplaceholder');\n\n        $collapsed_attr = ($a['collapsed']==='0' || $a['collapsed']==='1') ? $a['collapsed'] : $collapsed_default;\n\n        $code = (string)$content;\n        if ($code === '') $code = \"\/* \u628a\u7a0b\u5f0f\u78bc\u8cbc\u5728\u9019\u88e1 *\/\";\n        $code = esc_html($code); \/\/ \u6a19\u6e96\u6d41\u7a0b\uff08\u65b9\u6848A\uff09\uff0c\u65b9\u6848B\u7531 do_shortcode_tag \u6514\u622a\u539f\u6a23\n\n        $classes = 'psl-pre';\n        \/\/ \u82e5\u5168\u57df\u958b\u8457\u884c\u865f\uff0c\u6216\u55ae\u584a\u986f\u5f0f linenumbers=1\uff0c\u624d\u52a0\u4e0a\n        $global_ln = $this-&gt;opt('line_numbers',1);\n        if (($a['linenumbers'] === '1') || ($a['linenumbers'] === '' && $global_ln)) {\n            $classes .= ' line-numbers';\n        }\n\n        return '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"'.esc_attr($classes).'\" data-collapsed=\"'.\n               esc_attr($collapsed_attr).'\"&gt;&lt;code class=\"language-'.esc_attr($a['lang']).\n               '\" data-file=\"'.esc_attr($a['file']).'\"&gt;'.$code.'&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n    }\n\n    \/** \u5916\u90e8\u6a94\u6848\u77ed\u4ee3\u78bc\uff1a\u652f\u63f4\u767d\u540d\u55ae\u8def\u5f91 + \u526f\u6a94\u540d\u767d\u540d\u55ae *\/\n    public function shortcode_codefile($atts) {\n        $atts = shortcode_atts([\n            'src'       =&gt; '',\n            'lang'      =&gt; 'auto',\n            'collapsed' =&gt; '',\n            'file'      =&gt; '', \/\/ \u8986\u5beb\u53f3\u4e0a\u89d2\u6a94\u540d\u986f\u793a\n            'linenumbers' =&gt; '', \/\/ \u8986\u5beb\u884c\u865f\n        ], $atts, 'codefile');\n\n        if ($atts['src'] === '') {\n            return '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"psl-pre\"&gt;&lt;code&gt;\/* codefile\uff1a\u8acb\u63d0\u4f9b src \u5c6c\u6027 *\/&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n        }\n\n        $allowed_paths = $this-&gt;opt('allowed_paths', []);\n        $allowed_exts  = array_values(array_filter(array_map(function($e){\n            $e = strtolower(preg_replace('\/[^a-z0-9]\/','', trim($e)));\n            return $e;\n        }, explode(',', (string)$this-&gt;opt('allow_mimes','php,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx')))));\n\n        \/\/ \u82e5\u672a\u8a2d\u5b9a\u767d\u540d\u55ae\uff0c\u6cbf\u7528\u4f60\u539f\u672c uploads\/code-snippets\/ \u4f5c\u70ba\u56de\u9000\n        $uploads  = wp_upload_dir();\n        $fallback_base = trailingslashit($uploads['basedir']) . 'code-snippets';\n        if (!is_dir($fallback_base)) { wp_mkdir_p($fallback_base); }\n        if (empty($allowed_paths)) {\n            $real_bases = [ realpath($fallback_base) ];\n        } else {\n            $real_bases = array_values(array_filter(array_map(function($p){\n                $real = realpath($p);\n                return ($real && is_dir($real)) ? untrailingslashit($real) : null;\n            }, (array)$allowed_paths)));\n            \/\/ \u540c\u6642\u628a fallback \u4e5f\u52a0\u9032\u53bb\uff08\u4fdd\u7559\u76f8\u5bb9\uff09\n            $real_fb = realpath($fallback_base);\n            if ($real_fb) $real_bases[] = $real_fb;\n        }\n\n        \/\/ \u89e3\u6790\u76ee\u6a19\u6a94\u6848\u5be6\u9ad4\u8def\u5f91\uff08\u652f\u63f4\u76f8\u5c0d\u65bc\u767d\u540d\u55ae\u8def\u5f91\u7684 src\uff09\n        $candidate_paths = [];\n        foreach ($real_bases as $base) {\n            $candidate_paths[] = $base . '\/' . ltrim($atts['src'], '\/');\n        }\n        \/\/ \u540c\u6642\u5141\u8a31\u50b3\u5165\u7d55\u5c0d\u8def\u5f91\uff08\u82e5\u5728\u767d\u540d\u55ae\u4e4b\u4e0b\uff09\n        if (substr($atts['src'],0,1) === '\/' && file_exists($atts['src'])) {\n            $candidate_paths[] = $atts['src'];\n        }\n\n        $target_real = null;\n        foreach ($candidate_paths as $tgt) {\n            $real_tgt = realpath($tgt);\n            if (!$real_tgt || !is_file($real_tgt) || !is_readable($real_tgt)) continue;\n            \/\/ \u5fc5\u9808\u5728\u4efb\u4e00 base \u4e4b\u4e0b\n            $ok_base = false;\n            foreach ($real_bases as $base) {\n                if ($base && strpos($real_tgt, $base) === 0) { $ok_base = true; break; }\n            }\n            if (!$ok_base) continue;\n\n            \/\/ \u6a94\u6848\u526f\u6a94\u540d\u767d\u540d\u55ae\n            $ext = strtolower(pathinfo($real_tgt, PATHINFO_EXTENSION));\n            if (!in_array($ext, $allowed_exts, true)) continue;\n\n            $target_real = $real_tgt; break;\n        }\n\n        if (!$target_real) {\n            return '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"psl-pre\"&gt;&lt;code&gt;\/* codefile\uff1a\u6a94\u6848\u4e0d\u5728\u767d\u540d\u55ae\u6216\u526f\u6a94\u540d\u672a\u5141\u8a31\uff1a' . esc_html($atts['src']) . ' *\/&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n        }\n\n        \/\/ \u5927\u5c0f\u4e0a\u9650\uff08&gt;1MB \u62d2\u7d55\uff09\n        if (filesize($target_real) &gt; 1024 * 1024) {\n            return '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"psl-pre\"&gt;&lt;code&gt;\/* codefile\uff1a\u6a94\u6848\u904e\u5927\uff08&gt;1MB\uff09 *\/&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n        }\n\n        $raw  = file_get_contents($target_real);\n        $code = str_replace(['&lt;','&gt;'], ['&lt;','&gt;'], $raw);\n\n        \/\/ \u8a9e\u8a00\n        $lang = $atts['lang'];\n        if ($lang === 'auto' || $lang === '' ) {\n            $ext = strtolower(pathinfo($target_real, PATHINFO_EXTENSION));\n            $map = [\n                'php'=&gt;'php','phps'=&gt;'php','js'=&gt;'javascript','mjs'=&gt;'javascript','cjs'=&gt;'javascript',\n                'ts'=&gt;'typescript','tsx'=&gt;'tsx','css'=&gt;'css','scss'=&gt;'scss','sass'=&gt;'sass','less'=&gt;'less',\n                'html'=&gt;'markup','htm'=&gt;'markup','xml'=&gt;'markup','json'=&gt;'json','yml'=&gt;'yaml','yaml'=&gt;'yaml',\n                'py'=&gt;'python','rb'=&gt;'ruby','go'=&gt;'go','java'=&gt;'java','c'=&gt;'c','cpp'=&gt;'cpp','cs'=&gt;'csharp',\n                'sql'=&gt;'sql','sh'=&gt;'bash','bat'=&gt;'batch','md'=&gt;'markdown'\n            ];\n            $lang = $map[$ext] ?? 'markup';\n        }\n\n        $display_name = $atts['file'] !== '' ? $atts['file'] : basename($target_real);\n        $collapsed_default = !empty($this-&gt;opt('collapsed','0')) ? '1' : '0';\n        $collapsed_attr = ($atts['collapsed']==='0' || $atts['collapsed']==='1') ? $atts['collapsed'] : $collapsed_default;\n\n        $classes = 'psl-pre';\n        $global_ln = $this-&gt;opt('line_numbers',1);\n        if (($atts['linenumbers'] === '1') || ($atts['linenumbers'] === '' && $global_ln)) {\n            $classes .= ' line-numbers';\n        }\n\n        return '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"'.esc_attr($classes).'\" data-collapsed=\"' . esc_attr($collapsed_attr) .\n               '\"&gt;&lt;code class=\"language-' . esc_attr($lang) . '\" data-file=\"' . esc_attr($display_name) . '\"&gt;' . $code .\n               '&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n    }\n}\nPrism_Smart_Lite::init();\n\n\/* \u6b63\u898f\u5316\u5132\u5b58\u503c\uff08\u4fdd\u7559\u4f60\u7684\u9264\u5b50\uff0c\u4e26\u517c\u5bb9\u65b0\u6b04\u4f4d\uff09 *\/\nadd_action('pre_update_option_' . Prism_Smart_Lite::OPT_KEY, function($new){\n    $d = [\n        'theme'=&gt;'light','collapsed'=&gt;'0','max_width'=&gt;'100%','max_height'=&gt;'70vh',\n        'enqueue_mode'=&gt;'all','line_numbers'=&gt;1,'show_filename'=&gt;1,'enable_copy'=&gt;1,\n        'enable_collapse'=&gt;1,'enable_wrap_toggle'=&gt;0,'allow_mimes'=&gt;'php,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx',\n        'allowed_paths'=&gt;[]\n    ];\n    $new = is_array($new) ? array_merge($d, $new) : $d;\n\n    $new['theme']      = ($new['theme']==='dark') ? 'dark' : 'light';\n    $new['collapsed']  = (!empty($new['collapsed'])) ? '1' : '0';\n    $new['max_width']  = trim($new['max_width']  ?? '100%');\n    $new['max_height'] = trim($new['max_height'] ?? '70vh');\n\n    $new['enqueue_mode'] = in_array($new['enqueue_mode'], ['all','shortcode'], true) ? $new['enqueue_mode'] : 'all';\n    foreach (['line_numbers','show_filename','enable_copy','enable_collapse','enable_wrap_toggle'] as $k) {\n        $new[$k] = empty($new[$k]) ? 0 : 1;\n    }\n\n    \/\/ \u6e05\u7406 allow_mimes\n    $exts = array_filter(array_map('trim', explode(',', (string)$new['allow_mimes'])));\n    $exts = array_map(function($e){ return strtolower(preg_replace('\/[^a-z0-9]\/','',$e)); }, $exts);\n    $exts = array_values(array_unique(array_filter($exts)));\n    $new['allow_mimes'] = implode(',', $exts);\n\n    \/\/ \u8def\u5f91\u767d\u540d\u55ae\uff08\u9663\u5217\u6216\u591a\u884c\u5b57\u4e32\uff09\n    if (!is_array($new['allowed_paths'])) {\n        $paths_raw = explode(\"\\n\", (string)$new['allowed_paths']);\n        $clean = [];\n        foreach ($paths_raw as $p) {\n            $p = trim($p);\n            if ($p === '') continue;\n            $real = realpath($p);\n            if ($real && is_dir($real)) $clean[] = untrailingslashit($real);\n        }\n        $new['allowed_paths'] = array_values(array_unique($clean));\n    } else {\n        $new['allowed_paths'] = array_values(array_unique(array_map(function($p){\n            $p = trim((string)$p);\n            $real = realpath($p);\n            return ($real && is_dir($real)) ? untrailingslashit($real) : null;\n        }, $new['allowed_paths'])));\n        $new['allowed_paths'] = array_values(array_filter($new['allowed_paths']));\n    }\n\n    return $new;\n}, 10, 1);\n\n\/**\n * \ud83d\udeab \u5b8c\u6574\u4fdd\u7559\u77ed\u4ee3\u78bc\u5167\u539f\u6587\uff08\u4e0d\u8b93 WP \u6539\u52d5\u4efb\u4f55\u5b57\u5143\uff09\n * \u5229\u7528 do_shortcode_tag \u53d6\u5f97\u539f\u59cb\u5339\u914d\uff1a$m[5] \u662f\u77ed\u4ee3\u78bc\u5167\u6587\u539f\u6a23\n * \u53ea\u8f49\u7fa9 &lt; &gt;\uff0c\u907f\u514d\u88ab\u7576\u6210 HTML\uff0c\u5176\u4ed6\u5168\u90e8\u4fdd\u7559\n *\/\nadd_filter('do_shortcode_tag', function ($output, $tag, $attr, $m) {\n    if ($tag !== 'codeplaceholder' && $tag !== 'codebox') return $output;\n\n    \/\/ \u539f\u6a23\u5167\u6587\n    $raw = isset($m[5]) ? $m[5] : '';\n\n    \/\/ \u89e3\u6790\u5c6c\u6027\n    $atts = shortcode_parse_atts($m[3] ?? '') ?: [];\n    $opt = wp_parse_args(get_option(Prism_Smart_Lite::OPT_KEY, []), [\n        'collapsed'=&gt;'0','line_numbers'=&gt;1,'show_filename'=&gt;1\n    ]);\n\n    $file = isset($atts['file']) ? $atts['file'] : 'snippet.txt';\n    $lang = isset($atts['lang']) ? $atts['lang'] : 'markup';\n\n    $collapsed_default = !empty($opt['collapsed']) ? '1' : '0';\n    $collapsed_attr = (isset($atts['collapsed']) && ($atts['collapsed']==='0' || $atts['collapsed']==='1'))\n        ? $atts['collapsed']\n        : $collapsed_default;\n\n    $code = str_replace(['&lt;','&gt;'], ['&lt;','&gt;'], $raw);\n    if ($code === '') $code = \"\/* \u628a\u7a0b\u5f0f\u78bc\u8cbc\u5728\u9019\u88e1 *\/\";\n\n    $classes = 'psl-pre';\n    $ln_single = isset($atts['linenumbers']) ? $atts['linenumbers'] : '';\n    $global_ln = !empty($opt['line_numbers']);\n    if (($ln_single === '1') || ($ln_single === '' && $global_ln)) {\n        $classes .= ' line-numbers';\n    }\n\n    $html = '&lt;div class=\"psl-wrap\"&gt;&lt;pre class=\"'.esc_attr($classes).'\" data-collapsed=\"'.\n            esc_attr($collapsed_attr).'\"&gt;&lt;code class=\"language-'.esc_attr($lang).'\"'.\n            ' data-file=\"'.esc_attr($file).'\"&gt;'.$code.'&lt;\/code&gt;&lt;\/pre&gt;&lt;\/div&gt;';\n\n    return $html;\n}, 10, 4);\n\n\/**\n * \u26d4 \u6587\u7ae0\u82e5\u542b codeplaceholder\/codebox\uff0c\u66ab\u6642\u505c\u7528 WP \u81ea\u52d5\u8655\u7406\uff08\u907f\u514d\u4efb\u4f55\u6539\u5beb\uff09\n *\/\nadd_filter('the_content', function ($content) {\n    if (strpos($content, '[codeplaceholder') !== false || strpos($content, '[codebox') !== false) {\n        remove_filter('the_content', 'wpautop');\n        remove_filter('the_content', 'wptexturize');\n        remove_filter('the_content', 'convert_chars');\n        remove_filter('the_content', 'convert_smilies');\n    }\n    return $content;\n}, 0);\n\n\/** \u8a2d\u5b9a\u9801\uff08\u5206\u6a94\uff09 *\/\nrequire_once plugin_dir_path(__FILE__) . 'prism-smart-lite-settings.php';<\/code><\/pre><\/div>\n<hr \/>\n<h1>prism-smart-lite.php<\/h1>\n<div class=\"psl-wrap\"><pre class=\"psl-pre line-numbers\" data-collapsed=\"1\"><code class=\"language-php\" data-file=\"prism-smart-lite-settings.php\">&lt;?php\n\/**\n * Prism Smart Lite - Settings & File Manager (Enhanced with Folder Delete + Advanced Settings)\n * \u653e\u5230\u8207 prism-smart-lite.php \u540c\u4e00\u8cc7\u6599\u593e\n *\/\nif (!defined('ABSPATH')) exit;\n\n\/** ========= \u57fa\u672c\u5e38\u6578 \/ \u5e6b\u624b ========= *\/\ndefine('PSL_META_FILE', '.psl_meta.json');\n\nfunction psl_get_snippets_dir() {\n    $uploads = wp_upload_dir();\n    return trailingslashit($uploads['basedir']) . 'code-snippets';\n}\nfunction psl_ensure_snippets_dir() {\n    $dir = psl_get_snippets_dir();\n    if (!is_dir($dir)) wp_mkdir_p($dir);\n    return $dir;\n}\nfunction psl_htaccess_content() {\n    return \"Options -Indexes\\n&lt;FilesMatch \\\"\\\\.(php|phtml|phar)$\\\"&gt;\\n  Require all denied\\n&lt;\/FilesMatch&gt;\\n\";\n}\nfunction psl_is_our_settings_screen() {\n    return isset($_GET['page']) && $_GET['page'] === 'psl_settings';\n}\n\n\/** ========= \u76ee\u9304\/\u6a94\u6848\u6383\u63cf ========= *\/\nfunction psl_scan_files($dir) {\n    $out = [];\n    $real_base = realpath($dir);\n    if (!$real_base) return $out;\n    $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($real_base, FilesystemIterator::SKIP_DOTS));\n    foreach ($it as $file) {\n        if ($file-&gt;isFile()) {\n            $real = $file-&gt;getRealPath();\n            $rel = ltrim(str_replace($real_base, '', $real), '\/\\\\');\n            $out[] = [\n                'real'  =&gt; $real,\n                'rel'   =&gt; $rel,\n                'size'  =&gt; $file-&gt;getSize(),\n                'mtime' =&gt; $file-&gt;getMTime(),\n            ];\n        }\n    }\n    return $out;\n}\nfunction psl_scan_tree($base_dir) {\n    $base = realpath($base_dir);\n    $tree = [];\n    if (!$base) return $tree;\n\n    $it = new RecursiveDirectoryIterator($base, FilesystemIterator::SKIP_DOTS);\n    $rii = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);\n    foreach ($rii as $item) {\n        $rel = ltrim(str_replace($base, '', $item-&gt;getRealPath()), '\/\\\\');\n        $parts = $rel === '' ? [] : explode(DIRECTORY_SEPARATOR, $rel);\n        $node =& $tree;\n        foreach ($parts as $i =&gt; $p) {\n            if ($i === count($parts)-1) {\n                if ($item-&gt;isDir()) {\n                    if (!isset($node[$p])) $node[$p] = ['__type'=&gt;'dir','__children'=&gt;[]];\n                } else {\n                    $node[$p] = ['__type'=&gt;'file'];\n                }\n            } else {\n                if (!isset($node[$p])) $node[$p] = ['__type'=&gt;'dir','__children'=&gt;[]];\n                $node =& $node[$p]['__children'];\n            }\n        }\n    }\n    return ['__type'=&gt;'dir','__children'=&gt;$tree]; \/\/ root\n}\n\n\/** ========= \u63cf\u8ff0\u6a94\uff08JSON\uff09 ========= *\/\nfunction psl_meta_load($base_dir) {\n    $file = trailingslashit($base_dir) . PSL_META_FILE;\n    if (!file_exists($file)) return [];\n    $raw = file_get_contents($file);\n    $json = json_decode($raw, true);\n    return is_array($json) ? $json : [];\n}\nfunction psl_meta_save($base_dir, $data) {\n    $file = trailingslashit($base_dir) . PSL_META_FILE;\n    @file_put_contents($file, wp_json_encode($data, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT));\n    @chmod($file, 0644);\n}\nfunction psl_meta_get($base_dir, $rel) {\n    $m = psl_meta_load($base_dir);\n    return isset($m[$rel]) ? (string)$m[$rel] : '';\n}\nfunction psl_meta_set($base_dir, $rel, $desc) {\n    $m = psl_meta_load($base_dir);\n    if (trim($desc) === '') unset($m[$rel]);\n    else $m[$rel] = $desc;\n    psl_meta_save($base_dir, $m);\n}\nfunction psl_meta_delete($base_dir, $rel) {\n    $m = psl_meta_load($base_dir);\n    if (isset($m[$rel])) { unset($m[$rel]); psl_meta_save($base_dir, $m); }\n}\n\n\/** === A) Folder Delete Helpers: \u5b89\u5168\u522a\u9664\u76ee\u9304 + \u6e05\u7406\u63cf\u8ff0\uff08\u65b0\u589e\uff09 === *\/\nfunction psl_meta_prune_prefix($base_dir, $prefixRel) {\n    \/\/ \u522a\u9664 .psl_meta.json \u4e2d\u6240\u6709\u4ee5 prefix \u958b\u982d\u7684\u63cf\u8ff0\n    $m = psl_meta_load($base_dir);\n    $changed = false;\n    foreach ($m as $rel =&gt; $desc) {\n        if ($rel === $prefixRel || strpos($rel, rtrim($prefixRel,'\/').'\/') === 0) {\n            unset($m[$rel]); $changed = true;\n        }\n    }\n    if ($changed) psl_meta_save($base_dir, $m);\n}\nfunction psl_rrmdir($dir) {\n    if (!is_dir($dir)) return true;\n    $items = new FilesystemIterator($dir, FilesystemIterator::SKIP_DOTS);\n    foreach ($items as $item) {\n        if ($item-&gt;isDir()) {\n            psl_rrmdir($item-&gt;getPathname());\n        } else {\n            @unlink($item-&gt;getPathname());\n        }\n    }\n    return @rmdir($dir);\n}\n\n\/** ========= Admin Menu \/ Notices ========= *\/\nadd_action('admin_menu', function(){\n    add_options_page('Prism Smart Lite', 'Prism Smart Lite', 'manage_options', 'psl_settings', 'psl_render_settings_page');\n});\n\n\/* \uff081\uff09\u4fee\u6b63\u91cd\u8907\u986f\u793a\uff1a\u96c6\u4e2d\u5728 admin_notices \u55ae\u4e00\u8f38\u51fa\u4e00\u6b21 *\/\nadd_action('admin_notices', function(){\n    if (!current_user_can('manage_options')) return;\n    if (!psl_is_our_settings_screen()) return;\n    static $printed = false;\n    if ($printed) return;\n    $printed = true;\n    settings_errors('psl_msgs');\n});\n\n\/** ========= \u52d5\u4f5c\u8655\u7406 ========= *\/\nadd_action('admin_init', function(){\n    if (!current_user_can('manage_options')) return;\n\n    \/\/ \u5132\u5b58\u986f\u793a\u8a2d\u5b9a\uff08\u7dad\u6301\u539f\u672c\uff09\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_save_options' && check_admin_referer('psl_opts_nonce')) {\n        $o = get_option('psl_options', []);\n        $o['theme']      = (isset($_POST['psl_theme']) && $_POST['psl_theme']==='dark') ? 'dark' : 'light';\n        $o['collapsed']  = !empty($_POST['psl_collapsed']) ? '1' : '0';\n        $o['max_width']  = sanitize_text_field($_POST['psl_max_width'] ?? '100%');\n        $o['max_height'] = sanitize_text_field($_POST['psl_max_height'] ?? '70vh');\n        update_option('psl_options', $o);\n        add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u8a2d\u5b9a\u5df2\u5132\u5b58', 'updated');\n    }\n\n    \/\/ \u2705 \u65b0\u589e\uff1a\u5132\u5b58\u9032\u968e\u8a2d\u5b9a\uff08\u9375\u540d\u5c0d\u9f4a\u4e3b\u7a0b\u5f0f\uff09\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_save_advanced' && check_admin_referer('psl_adv_nonce')) {\n        $o = get_option('psl_options', []);\n        \/\/ select\n        $enqueue_mode = in_array(($_POST['psl_enqueue_mode'] ?? 'all'), ['all','shortcode'], true) ? $_POST['psl_enqueue_mode'] : 'all';\n        $o['enqueue_mode'] = $enqueue_mode;\n\n        \/\/ checkboxes \u2192 1\/0\n        foreach (['line_numbers','show_filename','enable_copy','enable_collapse','enable_wrap_toggle'] as $k) {\n            $o[$k] = !empty($_POST['psl_'.$k]) ? 1 : 0;\n        }\n\n        \/\/ allow_mimes\uff1a\u6e05\u7406\n        $exts = array_filter(array_map('trim', explode(',', (string)($_POST['psl_allow_mimes'] ?? ''))));\n        $exts = array_map(function($e){ return strtolower(preg_replace('\/[^a-z0-9]\/','',$e)); }, $exts);\n        $exts = array_values(array_unique(array_filter($exts)));\n        $o['allow_mimes'] = implode(',', $exts);\n\n        \/\/ allowed_paths\uff1a\u6bcf\u884c\u4e00\u500b\u76ee\u9304\uff0c\u50c5\u6536\u5b58\u5728\u7684\u8cc7\u6599\u593e\n        $paths_raw = explode(\"\\n\", (string)($_POST['psl_allowed_paths'] ?? ''));\n        $clean = [];\n        foreach ($paths_raw as $p) {\n            $p = trim($p);\n            if ($p === '') continue;\n            $real = realpath($p);\n            if ($real && is_dir($real)) $clean[] = untrailingslashit($real);\n        }\n        $o['allowed_paths'] = array_values(array_unique($clean));\n\n        update_option('psl_options', $o);\n        add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u9032\u968e\u8a2d\u5b9a\u5df2\u5132\u5b58', 'updated');\n    }\n\n    \/\/ \u751f\u6210\/\u522a\u9664 .htaccess\n    if (isset($_POST['psl_action']) && in_array($_POST['psl_action'], ['psl_gen_htaccess','psl_del_htaccess'], true) && check_admin_referer('psl_htaccess_nonce')) {\n        $dir  = psl_ensure_snippets_dir();\n        $file = $dir . '\/.htaccess';\n        if ($_POST['psl_action']==='psl_gen_htaccess') {\n            file_put_contents($file, psl_htaccess_content());\n            @chmod($file, 0644);\n            add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '.htaccess \u5df2\u751f\u6210', 'updated');\n        } else {\n            if (file_exists($file)) { unlink($file); add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '.htaccess \u5df2\u522a\u9664', 'updated'); }\n            else { add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '.htaccess \u4e0d\u5b58\u5728', 'error'); }\n        }\n    }\n\n    \/\/ \u6e2c\u8a66\u8def\u5f91\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_testpath' && check_admin_referer('psl_htaccess_nonce')) {\n        $dir = psl_ensure_snippets_dir();\n        $real = realpath($dir);\n        add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u57fa\u5e95\u8def\u5f91\uff1a' . esc_html($real), 'updated');\n    }\n\n    \/\/ \u5efa\u7acb\u8cc7\u6599\u593e\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_mkdir' && check_admin_referer('psl_mkdir_nonce')) {\n        $dir  = psl_ensure_snippets_dir();\n        $base = $dir;\n        $current = sanitize_text_field($_POST['psl_current'] ?? '');\n        if ($current !== '') $base = trailingslashit($dir) . $current;\n\n        $name = sanitize_text_field($_POST['psl_folder'] ?? '');\n        $name = trim($name, \"\/ \\t\\n\\r\\0\\x0B\");\n        if ($name !== '') {\n            $target = trailingslashit($base) . $name;\n            if (!is_dir($target)) {\n                wp_mkdir_p($target);\n                add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u5df2\u5efa\u7acb\u8cc7\u6599\u593e\uff1a' . esc_html(trim(($current ? $current.'\/' : '').$name,'\/')), 'updated');\n            } else {\n                add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u8cc7\u6599\u593e\u5df2\u5b58\u5728', 'error');\n            }\n        }\n    }\n\n    \/\/ \u4e0a\u50b3\u6a94\u6848\uff08\u53ef\u5beb\u5165\u63cf\u8ff0\uff09\uff0c\u652f\u63f4\u9078\u53d6\u7684\u76ee\u524d\u8cc7\u6599\u593e\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_upload' && check_admin_referer('psl_upload_nonce')) {\n        $dir = psl_ensure_snippets_dir();\n        $current = sanitize_text_field($_POST['psl_current'] ?? '');\n        $subdir  = trim($current !== '' ? $current : (sanitize_text_field($_POST['psl_subdir'] ?? '')), \"\/ \\t\\n\\r\\0\\x0B\");\n        $target_base = $dir;\n        if ($subdir !== '') {\n            $target_base = $dir . '\/' . $subdir;\n            if (!is_dir($target_base)) wp_mkdir_p($target_base);\n        }\n\n        if (!empty($_FILES['psl_file']) && $_FILES['psl_file']['error'] === UPLOAD_ERR_OK) {\n            $name = sanitize_file_name($_FILES['psl_file']['name']);\n            $target = $target_base . '\/' . $name;\n            $overwrite = !empty($_POST['psl_overwrite']);\n            if (file_exists($target) && !$overwrite) {\n                $name = time() . '-' . $name;\n                $target = $target_base . '\/' . $name;\n            }\n            if (move_uploaded_file($_FILES['psl_file']['tmp_name'], $target)) {\n                @chmod($target, 0644);\n                \/\/ \u5beb\u5165\u63cf\u8ff0\n                $desc = isset($_POST['psl_desc']) ? wp_kses_post($_POST['psl_desc']) : '';\n                $rel  = ltrim(str_replace(realpath($dir), '', realpath($target)), '\/\\\\');\n                if ($desc !== '') psl_meta_set($dir, $rel, $desc);\n                add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u6a94\u6848\u5df2\u4e0a\u50b3\uff1a' . esc_html(($subdir? $subdir.'\/' : '').basename($target)), 'updated');\n            } else {\n                add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u6a94\u6848\u4e0a\u50b3\u5931\u6557', 'error');\n            }\n        } else {\n            add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u672a\u9078\u64c7\u6a94\u6848\u6216\u4e0a\u50b3\u932f\u8aa4', 'error');\n        }\n    }\n\n    \/\/ \u522a\u9664\u6a94\u6848\uff08\u540c\u6b65\u79fb\u9664\u63cf\u8ff0\uff09\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_delete_file' && check_admin_referer('psl_delete_nonce')) {\n        $dir  = psl_ensure_snippets_dir();\n        $file = sanitize_text_field($_POST['psl_path'] ?? '');\n        $file = trim($file, \"\/ \");\n        $real = realpath($dir . '\/' . $file);\n        $real_base = realpath($dir);\n        if ($real && $real_base && strpos($real, $real_base) === 0 && is_file($real)) {\n            unlink($real);\n            psl_meta_delete($dir, $file);\n            add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u5df2\u522a\u9664\uff1a' . esc_html($file), 'updated');\n        } else {\n            add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u627e\u4e0d\u5230\u6a94\u6848\u6216\u7121\u6cd5\u522a\u9664', 'error');\n        }\n    }\n\n    \/\/ \u66f4\u65b0\u63cf\u8ff0\uff08\u5217\u8868\u5167\u5373\u6642\u7de8\u8f2f\uff09\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_update_desc' && check_admin_referer('psl_desc_nonce')) {\n        $dir  = psl_ensure_snippets_dir();\n        $file = sanitize_text_field($_POST['psl_path'] ?? '');\n        $desc = isset($_POST['psl_desc_edit']) ? wp_kses_post($_POST['psl_desc_edit']) : '';\n        \/\/ \u5b89\u5168\u6aa2\u67e5\u8def\u5f91\n        $real = realpath($dir . '\/' . $file);\n        $real_base = realpath($dir);\n        if ($real && $real_base && strpos($real, $real_base) === 0 && is_file($real)) {\n            psl_meta_set($dir, $file, $desc);\n            add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u63cf\u8ff0\u5df2\u66f4\u65b0\uff1a' . esc_html($file), 'updated');\n        } else {\n            add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u627e\u4e0d\u5230\u6a94\u6848\uff0c\u7121\u6cd5\u66f4\u65b0\u63cf\u8ff0', 'error');\n        }\n    }\n\n    \/\/ === D) \u522a\u9664\u8cc7\u6599\u593e\uff08\u65b0\u589e\u52d5\u4f5c\uff09 ===\n    if (isset($_POST['psl_action']) && $_POST['psl_action']==='psl_rmdir' && check_admin_referer('psl_rmdir_nonce')) {\n        $base = psl_ensure_snippets_dir();\n        $rel  = sanitize_text_field($_POST['psl_current'] ?? ''); \/\/ \u76ee\u524d\u9078\u53d6\u8cc7\u6599\u593e\uff08\u76f8\u5c0d\u65bc base\uff09\n        $recursive = !empty($_POST['psl_recursive']); \/\/ \u662f\u5426\u905e\u8ff4\u522a\u9664\n        $rel = trim($rel, \"\/ \");\n\n        if ($rel === '') {\n            add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u4e0d\u80fd\u522a\u9664\u6839\u76ee\u9304', 'error');\n        } else {\n            $real_base = realpath($base);\n            $target    = $real_base . '\/' . $rel;\n            $real_tgt  = realpath($target);\n\n            if (!$real_base || !$real_tgt || strpos($real_tgt, $real_base) !== 0 || !is_dir($real_tgt)) {\n                add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u8def\u5f91\u4e0d\u5408\u6cd5\u6216\u8cc7\u6599\u593e\u4e0d\u5b58\u5728', 'error');\n            } else {\n                if ($recursive) {\n                    if (psl_rrmdir($real_tgt)) {\n                        psl_meta_prune_prefix($base, $rel);\n                        add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u5df2\u522a\u9664\u8cc7\u6599\u593e\uff08\u542b\u6240\u6709\u5167\u5bb9\uff09\uff1a' . esc_html($rel), 'updated');\n                    } else {\n                        add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u522a\u9664\u5931\u6557', 'error');\n                    }\n                } else {\n                    $is_empty = true;\n                    $it = new FilesystemIterator($real_tgt, FilesystemIterator::SKIP_DOTS);\n                    foreach ($it as $x) { $is_empty = false; break; }\n                    if (!$is_empty) {\n                        add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u8cc7\u6599\u593e\u975e\u7a7a\uff0c\u8acb\u52fe\u9078\u300c\u540c\u6642\u522a\u9664\u5167\u5bb9\u300d', 'error');\n                    } else {\n                        if (@rmdir($real_tgt)) {\n                            psl_meta_prune_prefix($base, $rel);\n                            add_settings_error('psl_msgs', 'psl_ok_'.uniqid(), '\u5df2\u522a\u9664\u8cc7\u6599\u593e\uff1a' . esc_html($rel), 'updated');\n                        } else {\n                            add_settings_error('psl_msgs', 'psl_err_'.uniqid(), '\u522a\u9664\u5931\u6557', 'error');\n                        }\n                    }\n                }\n            }\n        }\n    }\n});\n\n\/** ========= \u8a2d\u5b9a\u9801\u9762 ========= *\/\nfunction psl_render_settings_page() {\n    if (!current_user_can('manage_options')) return;\n\n    $dir      = psl_ensure_snippets_dir();\n    $real_dir = realpath($dir);\n    $htpath   = $dir . '\/.htaccess';\n    $has_ht   = file_exists($htpath);\n    $files    = psl_scan_files($dir);\n    $tree     = psl_scan_tree($dir);\n    $meta     = psl_meta_load($dir);\n\n    \/\/ \u8b80\u53d6\u76ee\u524d\u9078\u9805\uff08\u542b\u9032\u968e\uff1b\u4e3b\u7a0b\u5f0f\u6703\u7528\u5230\uff09\n    $opts_def = [\n        'theme'=&gt;'light','collapsed'=&gt;'0','max_width'=&gt;'100%','max_height'=&gt;'70vh',\n        'enqueue_mode'=&gt;'all','line_numbers'=&gt;1,'show_filename'=&gt;1,'enable_copy'=&gt;1,'enable_collapse'=&gt;1,'enable_wrap_toggle'=&gt;0,\n        'allow_mimes'=&gt;'php,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx','allowed_paths'=&gt;[]\n    ];\n    $opts = wp_parse_args(get_option('psl_options', []), $opts_def);\n    ?&gt;\n    &lt;div class=\"wrap\"&gt;\n        &lt;h1&gt;Prism Smart Lite \u2014 \u8a2d\u5b9a\u8207\u6a94\u6848\u7ba1\u7406&lt;\/h1&gt;\n\n        &lt;h2&gt;\u986f\u793a\u8a2d\u5b9a&lt;\/h2&gt;\n        &lt;form method=\"post\"&gt;\n            &lt;?php wp_nonce_field('psl_opts_nonce'); ?&gt;\n            &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_save_options\"&gt;\n            &lt;table class=\"form-table\"&gt;\n                &lt;tr&gt;&lt;th&gt;\u4e3b\u984c&lt;\/th&gt;&lt;td&gt;\n                    &lt;label&gt;&lt;input type=\"radio\" name=\"psl_theme\" value=\"light\" &lt;?php checked($opts['theme'],'light'); ?&gt;&gt; \u4eae\u8272&lt;\/label&gt;\n                    &lt;label style=\"margin-left:10px;\"&gt;&lt;input type=\"radio\" name=\"psl_theme\" value=\"dark\" &lt;?php checked($opts['theme'],'dark'); ?&gt;&gt; \u6697\u8272&lt;\/label&gt;\n                &lt;\/td&gt;&lt;\/tr&gt;\n                &lt;tr&gt;&lt;th&gt;\u9810\u8a2d\u6536\u5408&lt;\/th&gt;&lt;td&gt;\n                    &lt;label&gt;&lt;input type=\"checkbox\" name=\"psl_collapsed\" value=\"1\" &lt;?php checked($opts['collapsed'],'1'); ?&gt;&gt; \u9810\u8a2d\u6536\u5408&lt;\/label&gt;\n                &lt;\/td&gt;&lt;\/tr&gt;\n                &lt;tr&gt;&lt;th&gt;\u986f\u793a\u5bec\u5ea6&lt;\/th&gt;&lt;td&gt;&lt;input type=\"text\" name=\"psl_max_width\" value=\"&lt;?php echo esc_attr($opts['max_width']); ?&gt;\"&gt;\uff08\u4f8b\u5982 100% \u6216 960px\uff09&lt;\/td&gt;&lt;\/tr&gt;\n                &lt;tr&gt;&lt;th&gt;\u672a\u6536\u5408\u6700\u5927\u9ad8\u5ea6&lt;\/th&gt;&lt;td&gt;&lt;input type=\"text\" name=\"psl_max_height\" value=\"&lt;?php echo esc_attr($opts['max_height']); ?&gt;\"&gt;\uff08\u4f8b\u5982 70vh \u6216 560px\uff09&lt;\/td&gt;&lt;\/tr&gt;\n            &lt;\/table&gt;\n            &lt;?php submit_button('\u5132\u5b58\u986f\u793a\u8a2d\u5b9a'); ?&gt;\n        &lt;\/form&gt;\n\n        &lt;!-- \u2705 \u9032\u968e\u8a2d\u5b9a\uff08\u540c\u9801\uff09 --&gt;\n        &lt;h2 style=\"margin-top:24px;\"&gt;\u9032\u968e\u8a2d\u5b9a&lt;\/h2&gt;\n        &lt;form method=\"post\"&gt;\n            &lt;?php wp_nonce_field('psl_adv_nonce'); ?&gt;\n            &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_save_advanced\"&gt;\n            &lt;table class=\"form-table\"&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;\u8cc7\u6e90\u8f09\u5165&lt;\/th&gt;\n                    &lt;td&gt;\n                        &lt;label&gt;&lt;input type=\"radio\" name=\"psl_enqueue_mode\" value=\"all\" &lt;?php checked($opts['enqueue_mode'],'all'); ?&gt;&gt; \u6240\u6709\u524d\u7aef\u9801\u9762&lt;\/label&gt;\n                        &lt;label style=\"margin-left:10px;\"&gt;&lt;input type=\"radio\" name=\"psl_enqueue_mode\" value=\"shortcode\" &lt;?php checked($opts['enqueue_mode'],'shortcode'); ?&gt;&gt; \u50c5\u5075\u6e2c\u5230\u77ed\u4ee3\u78bc\u6642&lt;\/label&gt;\n                    &lt;\/td&gt;\n                &lt;\/tr&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;\u884c\u865f&lt;\/th&gt;\n                    &lt;td&gt;&lt;label&gt;&lt;input type=\"checkbox\" name=\"psl_line_numbers\" value=\"1\" &lt;?php checked(!empty($opts['line_numbers'])); ?&gt;&gt; \u986f\u793a\u884c\u865f\uff08\u53ef\u5728\u55ae\u4e00\u77ed\u4ee3\u78bc\u7528 &lt;code&gt;linenumbers=\"0|1\"&lt;\/code&gt; \u8986\u5beb\uff09&lt;\/label&gt;&lt;\/td&gt;\n                &lt;\/tr&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;\u5de5\u5177\u5217&lt;\/th&gt;\n                    &lt;td&gt;\n                        &lt;label&gt;&lt;input type=\"checkbox\" name=\"psl_show_filename\" value=\"1\" &lt;?php checked(!empty($opts['show_filename'])); ?&gt;&gt; \u6a94\u540d\u5fbd\u7ae0&lt;\/label&gt;\n                        &lt;label style=\"margin-left:10px;\"&gt;&lt;input type=\"checkbox\" name=\"psl_enable_copy\" value=\"1\" &lt;?php checked(!empty($opts['enable_copy'])); ?&gt;&gt; \u8907\u88fd\u6309\u9215&lt;\/label&gt;\n                        &lt;label style=\"margin-left:10px;\"&gt;&lt;input type=\"checkbox\" name=\"psl_enable_collapse\" value=\"1\" &lt;?php checked(!empty($opts['enable_collapse'])); ?&gt;&gt; \u6536\u5408\/\u5c55\u958b\u6309\u9215&lt;\/label&gt;\n                        &lt;label style=\"margin-left:10px;\"&gt;&lt;input type=\"checkbox\" name=\"psl_enable_wrap_toggle\" value=\"1\" &lt;?php checked(!empty($opts['enable_wrap_toggle'])); ?&gt;&gt; \u63db\u884c\u5207\u63db\u6309\u9215&lt;\/label&gt;\n                    &lt;\/td&gt;\n                &lt;\/tr&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;\u5141\u8a31\u526f\u6a94\u540d&lt;\/th&gt;\n                    &lt;td&gt;\n                        &lt;input type=\"text\" class=\"regular-text\" name=\"psl_allow_mimes\" value=\"&lt;?php echo esc_attr($opts['allow_mimes']); ?&gt;\"&gt;\n                        &lt;p class=\"description\"&gt;\u4ee5\u9017\u865f\u5206\u9694\uff0c\u4f8b\u5982\uff1aphp,js,css,html,txt,md,json,xml,yml,yaml,ts,tsx&lt;\/p&gt;\n                    &lt;\/td&gt;\n                &lt;\/tr&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;\u5141\u8a31\u8b80\u6a94\u8def\u5f91\uff08\u767d\u540d\u55ae\uff09&lt;\/th&gt;\n                    &lt;td&gt;\n                        &lt;textarea class=\"large-text code\" rows=\"4\" name=\"psl_allowed_paths\" placeholder=\"\/var\/www\/mysite\/wp-content\/uploads\/code-snippets&#10;\/data\/shared\/snippets\"&gt;&lt;?php\n                            echo esc_textarea(implode(\"\\n\", (array)$opts['allowed_paths']));\n                        ?&gt;&lt;\/textarea&gt;\n                        &lt;p class=\"description\"&gt;\u6bcf\u884c\u4e00\u500b\u7d55\u5c0d\u8def\u5f91\uff1b\u50c5\u52a0\u5165\u5b58\u5728\u7684\u8cc7\u6599\u593e\u3002\u82e5\u7559\u7a7a\u5247\u6cbf\u7528\u4e0a\u50b3\u76ee\u9304\u4e2d\u7684 &lt;code&gt;code-snippets\/&lt;\/code&gt;\uff08\u5df2\u76f8\u5bb9\uff09\u3002&lt;\/p&gt;\n                    &lt;\/td&gt;\n                &lt;\/tr&gt;\n            &lt;\/table&gt;\n            &lt;?php submit_button('\u5132\u5b58\u9032\u968e\u8a2d\u5b9a'); ?&gt;\n        &lt;\/form&gt;\n\n        &lt;hr&gt;\n\n        &lt;h2&gt;\u6a94\u6848\u7ba1\u7406\uff08code-snippets\uff09&lt;\/h2&gt;\n        &lt;p&gt;\u5132\u5b58\u4f4d\u7f6e\uff1a &lt;code&gt;&lt;?php echo esc_html($real_dir); ?&gt;&lt;\/code&gt;&lt;\/p&gt;\n        &lt;p style=\"margin-bottom:10px;\"&gt;\n            &lt;form method=\"post\" style=\"display:inline;\"&gt;\n                &lt;?php wp_nonce_field('psl_htaccess_nonce'); ?&gt;\n                &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_gen_htaccess\"&gt;\n                &lt;input type=\"submit\" class=\"button\" value=\"\u751f\u6210 .htaccess\"&gt;\n            &lt;\/form&gt;\n            &lt;form method=\"post\" style=\"display:inline;margin-left:10px;\"&gt;\n                &lt;?php wp_nonce_field('psl_htaccess_nonce'); ?&gt;\n                &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_del_htaccess\"&gt;\n                &lt;input type=\"submit\" class=\"button\" value=\"\u522a\u9664 .htaccess\"&gt;\n            &lt;\/form&gt;\n            &lt;form method=\"post\" style=\"display:inline;margin-left:10px;\"&gt;\n                &lt;?php wp_nonce_field('psl_htaccess_nonce'); ?&gt;\n                &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_testpath\"&gt;\n                &lt;input type=\"submit\" class=\"button\" value=\"\u8def\u5f91\u89e3\u6790\u6e2c\u8a66\"&gt;\n            &lt;\/form&gt;\n            &lt;span style=\"margin-left:12px;\"&gt;.htaccess \u72c0\u614b\uff1a&lt;?php echo $has_ht ? '&lt;span style=\"color:green\"&gt;\u5b58\u5728&lt;\/span&gt;' : '&lt;span style=\"color:gray\"&gt;\u4e0d\u5b58\u5728&lt;\/span&gt;'; ?&gt;&lt;\/span&gt;\n        &lt;\/p&gt;\n\n        &lt;div id=\"psl-fm\" style=\"display:flex;gap:20px;align-items:flex-start;\"&gt;\n            &lt;!-- \u5de6\u5074\uff1a\u8cc7\u6599\u593e\u6a39 --&gt;\n            &lt;div style=\"flex:0 0 280px;\"&gt;\n                &lt;h3&gt;\u8cc7\u6599\u593e&lt;\/h3&gt;\n                &lt;div class=\"psl-tree\" id=\"psl-tree\" style=\"border:1px solid #ddd;padding:8px;border-radius:6px;max-height:420px;overflow:auto;\"&gt;\n                    &lt;?php echo psl_render_tree_html($tree, ''); ?&gt;\n                &lt;\/div&gt;\n\n                &lt;!-- \u65b0\u589e\u8cc7\u6599\u593e --&gt;\n                &lt;form method=\"post\" style=\"margin-top:12px;\"&gt;\n                    &lt;?php wp_nonce_field('psl_mkdir_nonce'); ?&gt;\n                    &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_mkdir\"&gt;\n                    &lt;input type=\"hidden\" id=\"psl_current_input\" name=\"psl_current\" value=\"\"&gt;\n                    &lt;label&gt;\u5728\u76ee\u524d\u8cc7\u6599\u593e\u65b0\u589e\uff1a&lt;br&gt;\n                        &lt;input type=\"text\" name=\"psl_folder\" placeholder=\"\u65b0\u8cc7\u6599\u593e\u540d\u7a31\" class=\"regular-text\"&gt;\n                    &lt;\/label&gt;\n                    &lt;p style=\"margin-top:6px;\"&gt;&lt;button class=\"button\"&gt;\u5efa\u7acb\u8cc7\u6599\u593e&lt;\/button&gt;&lt;\/p&gt;\n                &lt;\/form&gt;\n\n                &lt;!-- \u522a\u9664\u8cc7\u6599\u593e\uff08\u6703\u986f\u793a\u540d\u7a31\uff09 --&gt;\n                &lt;form method=\"post\" style=\"margin-top:12px;\"&gt;\n                    &lt;?php wp_nonce_field('psl_rmdir_nonce'); ?&gt;\n                    &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_rmdir\"&gt;\n                    &lt;input type=\"hidden\" id=\"psl_current_delete\" name=\"psl_current\" value=\"\"&gt;\n                    &lt;p&gt;&lt;strong id=\"psl-delete-caption\"&gt;\u522a\u9664\u76ee\u524d\u8cc7\u6599\u593e&lt;\/strong&gt;&lt;\/p&gt;\n                    &lt;label&gt;\n                        &lt;input type=\"checkbox\" name=\"psl_recursive\" value=\"1\"&gt;\n                        \u540c\u6642\u522a\u9664\u5167\u5bb9\uff08\u905e\u8ff4\u522a\u9664\uff09\n                    &lt;\/label&gt;\n                    &lt;p style=\"margin-top:6px;\"&gt;\n                        &lt;button class=\"button button-secondary\" onclick=\"return confirm('\u78ba\u5b9a\u8981\u522a\u9664\u6240\u9078\u8cc7\u6599\u593e\uff1f');\"&gt;\u522a\u9664\u8cc7\u6599\u593e&lt;\/button&gt;\n                    &lt;\/p&gt;\n                    &lt;p class=\"description\"&gt;\u7121\u6cd5\u522a\u9664\u6839\u76ee\u9304\uff1b\u4e0d\u52fe\u9078\u6642\u50c5\u5141\u8a31\u522a\u9664\u7a7a\u76ee\u9304\u3002&lt;\/p&gt;\n                &lt;\/form&gt;\n            &lt;\/div&gt;\n\n            &lt;!-- \u53f3\u5074\uff1a\u4e0a\u50b3 + \u6a94\u6848\u6e05\u55ae --&gt;\n            &lt;div style=\"flex:1 1 auto;\"&gt;\n                &lt;h3&gt;\u4e0a\u50b3\u6a94\u6848&lt;\/h3&gt;\n                &lt;form method=\"post\" enctype=\"multipart\/form-data\" id=\"psl-upload-form\"&gt;\n                    &lt;?php wp_nonce_field('psl_upload_nonce'); ?&gt;\n                    &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_upload\"&gt;\n                    &lt;input type=\"hidden\" id=\"psl_current_upload\" name=\"psl_current\" value=\"\"&gt;\n                    &lt;table class=\"form-table\"&gt;\n                        &lt;tr&gt;\n                            &lt;th&gt;\u76ee\u524d\u8def\u5f91&lt;\/th&gt;\n                            &lt;td&gt;&lt;code id=\"psl-current-path\"&gt;(\u6839\u76ee\u9304)&lt;\/code&gt;&lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th&gt;\u6a94\u6848&lt;\/th&gt;&lt;td&gt;&lt;input type=\"file\" name=\"psl_file\" required&gt;&lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th&gt;\u63cf\u8ff0&lt;\/th&gt;\n                            &lt;td&gt;&lt;textarea name=\"psl_desc\" class=\"large-text code\" rows=\"3\" placeholder=\"\u70ba\u9019\u500b\u6a94\u6848\u65b0\u589e\u63cf\u8ff0\uff08\u53ef\u7a7a\u767d\uff09\"&gt;&lt;\/textarea&gt;&lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th&gt;\u91cd\u8907\u6a94\u540d&lt;\/th&gt;\n                            &lt;td&gt;&lt;label&gt;&lt;input type=\"checkbox\" name=\"psl_overwrite\" value=\"1\"&gt; \u8986\u84cb\uff08\u4e0d\u52fe\u9078\u5247\u81ea\u52d5\u52a0\u4e0a\u6642\u9593\u6233\u4ee5\u907f\u514d\u8986\u84cb\uff09&lt;\/label&gt;&lt;\/td&gt;\n                        &lt;\/tr&gt;\n                    &lt;\/table&gt;\n                    &lt;?php submit_button('\u4e0a\u50b3'); ?&gt;\n                &lt;\/form&gt;\n\n                &lt;h3 style=\"margin-top:1.5em\"&gt;\u6a94\u6848\u6e05\u55ae&lt;\/h3&gt;\n                &lt;p&gt;\u53ef\u5728\u4e0b\u65b9\u76f4\u63a5\u522a\u9664\u6216\u7de8\u8f2f\u63cf\u8ff0\uff1b\u9ede\u9078\u5de6\u5074\u8cc7\u6599\u593e\u53ef\u7be9\u9078\u3002&lt;\/p&gt;\n\n                &lt;table class=\"widefat striped\" id=\"psl-file-table\"&gt;\n                    &lt;thead&gt;&lt;tr&gt;&lt;th&gt;\u6a94\u540d\uff08\u76f8\u5c0d\u8def\u5f91\uff09&lt;\/th&gt;&lt;th style=\"width:12%\"&gt;\u5927\u5c0f&lt;\/th&gt;&lt;th style=\"width:18%\"&gt;\u4fee\u6539\u6642\u9593&lt;\/th&gt;&lt;th&gt;\u63cf\u8ff0&lt;\/th&gt;&lt;th style=\"width:120px\"&gt;\u52d5\u4f5c&lt;\/th&gt;&lt;\/tr&gt;&lt;\/thead&gt;\n                    &lt;tbody&gt;\n                        &lt;?php if (!empty($files)): foreach ($files as $f): \n                            $rel = $f['rel'];\n                            $desc = isset($meta[$rel]) ? $meta[$rel] : '';\n                        ?&gt;\n                        &lt;tr data-rel=\"&lt;?php echo esc_attr($rel); ?&gt;\"&gt;\n                            &lt;td&gt;&lt;code&gt;&lt;?php echo esc_html($rel); ?&gt;&lt;\/code&gt;&lt;\/td&gt;\n                            &lt;td&gt;&lt;?php echo esc_html(size_format($f['size'])); ?&gt;&lt;\/td&gt;\n                            &lt;td&gt;&lt;?php echo esc_html(date('Y-m-d H:i:s', $f['mtime'])); ?&gt;&lt;\/td&gt;\n                            &lt;td&gt;\n                                &lt;form method=\"post\" class=\"psl-desc-form\" style=\"display:flex;gap:6px;align-items:flex-start;\"&gt;\n                                    &lt;?php wp_nonce_field('psl_desc_nonce'); ?&gt;\n                                    &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_update_desc\"&gt;\n                                    &lt;input type=\"hidden\" name=\"psl_path\" value=\"&lt;?php echo esc_attr($rel); ?&gt;\"&gt;\n                                    &lt;textarea name=\"psl_desc_edit\" class=\"regular-text code\" rows=\"2\" style=\"width:100%;\"&gt;&lt;?php echo esc_textarea($desc); ?&gt;&lt;\/textarea&gt;\n                                    &lt;button class=\"button\"&gt;\u5132\u5b58&lt;\/button&gt;\n                                &lt;\/form&gt;\n                            &lt;\/td&gt;\n                            &lt;td&gt;\n                                &lt;form method=\"post\" style=\"display:inline;\"&gt;\n                                    &lt;?php wp_nonce_field('psl_delete_nonce'); ?&gt;\n                                    &lt;input type=\"hidden\" name=\"psl_action\" value=\"psl_delete_file\"&gt;\n                                    &lt;input type=\"hidden\" name=\"psl_path\" value=\"&lt;?php echo esc_attr($rel); ?&gt;\"&gt;\n                                    &lt;input type=\"submit\" class=\"button-link delete-link\" value=\"\u522a\u9664\" onclick=\"return confirm('\u78ba\u5b9a\u8981\u522a\u9664\u55ce\uff1f');\"&gt;\n                                &lt;\/form&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;?php endforeach; else: ?&gt;\n                        &lt;tr&gt;&lt;td colspan=\"5\"&gt;\u76ee\u524d\u8cc7\u6599\u593e\u4e2d\u6c92\u6709\u6a94\u6848\u3002&lt;\/td&gt;&lt;\/tr&gt;\n                        &lt;?php endif; ?&gt;\n                    &lt;\/tbody&gt;\n                &lt;\/table&gt;\n\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n\n    &lt;style&gt;\n    .psl-tree ul{ list-style:none; margin:0 0 0 14px; padding:0; }\n    .psl-tree li{ margin:2px 0; }\n    .psl-tree .folder{ cursor:pointer; user-select:none; }\n    .psl-tree .folder:before{ content:\"\ud83d\udcc1 \"; }\n    .psl-tree .file:before{ content:\"\ud83d\udcc4 \"; }\n    .psl-tree .active{ background:#f0f6ff; border-radius:4px; }\n    #psl-file-table tbody tr[hidden]{ display:none; }\n    &lt;\/style&gt;\n\n    &lt;script&gt;\n    (function(){\n        \/\/ \u9ede\u9078\u8cc7\u6599\u593e \u2192 \u8a2d\u5b9a\u76ee\u524d\u8def\u5f91\u3001\u7be9\u9078\u6e05\u55ae\u3001\u540c\u6b65\u4e0a\u50b3\/\u65b0\u589e\/\u522a\u9664\u8cc7\u6599\u593e\u8868\u55ae\n        const tree = document.getElementById('psl-tree');\n        const curPathText = document.getElementById('psl-current-path');\n        const curInput = document.getElementById('psl_current_input');\n        const curUpload = document.getElementById('psl_current_upload');\n        const curDelete = document.getElementById('psl_current_delete'); \/\/ \u522a\u9664\u8cc7\u6599\u593e\u8868\u55ae\n        const delCaption = document.getElementById('psl-delete-caption'); \/\/ \u986f\u793a\u300c\u522a\u9664\u76ee\u524d\u8cc7\u6599\u593e\uff08\u540d\u7a31\uff09\u300d\n        const rows = document.querySelectorAll('#psl-file-table tbody tr');\n\n        function folderCaption(path){\n            if (!path) return '\u522a\u9664\u76ee\u524d\u8cc7\u6599\u593e\uff08\u6839\u76ee\u9304\u4e0d\u53ef\u522a\uff09';\n            return '\u522a\u9664\u76ee\u524d\u8cc7\u6599\u593e\uff08' + path + '\uff09';\n        }\n\n        function selectFolder(path){\n            \/\/ \u9ad8\u4eae\n            tree.querySelectorAll('.folder').forEach(el =&gt; el.classList.remove('active'));\n            const node = tree.querySelector('[data-path=\"'+path+'\"]');\n            if (node) node.classList.add('active');\n\n            \/\/ \u986f\u793a\u76ee\u524d\u8def\u5f91\n            curPathText.textContent = path ? path : '(\u6839\u76ee\u9304)';\n            curInput.value = path;\n            curUpload.value = path;\n            if (curDelete) curDelete.value = path; \/\/ \u540c\u6b65\u5230\u522a\u9664\u8868\u55ae\n            if (delCaption) delCaption.textContent = folderCaption(path);\n\n            \/\/ \u7be9\u9078\u8868\u683c\n            rows.forEach(tr =&gt; {\n                const rel = tr.getAttribute('data-rel');\n                if (!path) { tr.hidden = false; return; }\n                tr.hidden = !(rel.startsWith(path + '\/') || rel === path);\n            });\n        }\n\n        \/\/ \u6a39\u72c0\u4e8b\u4ef6\u4ee3\u7406\n        tree.addEventListener('click', function(e){\n            const li = e.target.closest('.folder');\n            if (!li) return;\n            const path = li.getAttribute('data-path') || '';\n            const sub = li.nextElementSibling; \/\/ UL\n            if (sub && sub.tagName === 'UL') sub.hidden = !sub.hidden;\n            selectFolder(path);\n        });\n\n        \/\/ \u9810\u8a2d\u9078\u6839\u76ee\u9304\n        selectFolder('');\n\n        \/\/ \u8b93\u5de6\u6a39\u7b2c\u4e8c\u5c64\u9810\u8a2d\u5c55\u958b\n        tree.querySelectorAll('.psl-tree ul ul').forEach(ul =&gt; ul.hidden = false);\n    })();\n    &lt;\/script&gt;\n    &lt;?php\n}\n\n\/** ========= \u7522\u751f\u6a39\u72c0 HTML ========= *\/\nfunction psl_render_tree_html($node, $prefix) {\n    \/\/ $node: ['__type'=&gt;'dir','__children'=&gt;[ name =&gt; (dir|file), ... ]]\n    if (!is_array($node) || ($node['__type'] ?? '') !== 'dir') return '';\n    $html = '&lt;ul&gt;';\n    \/\/ \u6839\u76ee\u9304\u6309\u9215\n    if ($prefix === '') {\n        $html .= '&lt;li&gt;&lt;span class=\"folder active\" data-path=\"\"&gt;(\u6839\u76ee\u9304)&lt;\/span&gt;&lt;\/li&gt;';\n    }\n    \/\/ \u6392\u5e8f\uff1a\u8cc7\u6599\u593e\u5728\u524d\u3001\u6a94\u6848\u5728\u5f8c\n    $dirs = $files = [];\n    foreach (($node['__children'] ?? []) as $name =&gt; $item) {\n        if (is_array($item) && ($item['__type'] ?? '') === 'dir') $dirs[$name] = $item;\n        else $files[$name] = $item;\n    }\n    ksort($dirs, SORT_NATURAL|SORT_FLAG_CASE);\n    ksort($files, SORT_NATURAL|SORT_FLAG_CASE);\n\n    foreach ($dirs as $name =&gt; $child) {\n        $path = ltrim($prefix . '\/' . $name, '\/');\n        $html .= '&lt;li&gt;&lt;span class=\"folder\" data-path=\"'.esc_attr($path).'\"&gt;'.esc_html($name).'&lt;\/span&gt;';\n        $html .= psl_render_tree_html($child, $path);\n        $html .= '&lt;\/li&gt;';\n    }\n    foreach ($files as $name =&gt; $child) {\n        $path = ltrim($prefix . '\/' . $name, '\/');\n        $html .= '&lt;li&gt;&lt;span class=\"file\" data-path=\"'.esc_attr($path).'\"&gt;'.esc_html($name).'&lt;\/span&gt;&lt;\/li&gt;';\n    }\n    $html .= '&lt;\/ul&gt;';\n    return $html;\n}<\/code><\/pre><\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Prism Smart Lite \u662f\u4e00\u6b3e\u70ba WordPress \u6253\u9020\u7684\u8f15\u91cf\u7a0b\u5f0f\u78bc &hellip; <a href=\"https:\/\/www.myclass-lin.org\/wordpress\/archives\/1257\">\u95b1\u8b80\u5168\u6587 <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[18],"class_list":["post-1257","post","type-post","status-publish","format-standard","hentry","category-wordpress","tag-chatgpt"],"_links":{"self":[{"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/posts\/1257","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/comments?post=1257"}],"version-history":[{"count":0,"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/posts\/1257\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/media?parent=1257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/categories?post=1257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.myclass-lin.org\/wordpress\/wp-json\/wp\/v2\/tags?post=1257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}