<?php
/**
* Typecho 代码高亮插件 (Prism.js)
* 集成:CDN 加速、行号显示、长代码折叠、一键复制。
* @package SimplePrism
* @author 小野博客
* @version 1.2.0
* @link https://lb5.net
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
class SimplePrism_Plugin implements Typecho_Plugin_Interface
{
const PRISM_VER = '1.29.0';
const CDN_BASE = 'https://cdn.staticfile.org/prism/1.29.0';
const CLIPBOARD_CDN = 'https://cdn.staticfile.org/clipboard.js/2.0.11/clipboard.min.js';
public static function activate()
{
Typecho_Plugin::factory('Widget_Archive')->header = array('SimplePrism_Plugin', 'header');
Typecho_Plugin::factory('Widget_Archive')->footer = array('SimplePrism_Plugin', 'footer');
}
public static function deactivate(){}
public static function config(Typecho_Widget_Helper_Form $form)
{
$theme = new Typecho_Widget_Helper_Form_Element_Select('theme', array(
'prism.min.css' => 'Default (浅色)',
'prism-okaidia.min.css' => 'Okaidia (深色/推荐)',
'prism-tomorrow.min.css'=> 'Tomorrow (浅色柔和)',
'prism-twilight.min.css'=> 'Twilight (深色)',
'prism-solarizedlight.min.css' => 'Solarized Light',
), 'prism-okaidia.min.css', _t('高亮主题'), _t(' 选择代码块配色方案。'));
$form->addInput($theme);
$lineNumbers = new Typecho_Widget_Helper_Form_Element_Radio('lineNumbers', array(
'1' => '开启',
'0' => '关闭'
), '1', _t('显示行号'), _t(' 是否显示行号。'));
$form->addInput($lineNumbers);
$enableCopy = new Typecho_Widget_Helper_Form_Element_Radio('enableCopy', array(
'1' => '开启',
'0' => '关闭'
), '1', _t('启用一键复制'), _t(' 在代码块右上角显示“复制”按钮。'));
$form->addInput($enableCopy);
$maxHeight = new Typecho_Widget_Helper_Form_Element_Text('maxHeight', NULL, '400', _t(' 折叠阈值 (px)'), _t(' 超过此高度自动折叠。填 0 关闭此功能。'));
$form->addInput($maxHeight);
}
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
public static function header()
{
$options = Typecho_Widget::widget('Widget_Options')->plugin('SimplePrism');
echo '<link rel="stylesheet" href="' . self::CDN_BASE . '/themes/' . $options->theme . '" />' . "\n";
if ($options->enableCopy) {
echo '<link rel="stylesheet" href="' . self::CDN_BASE . '/plugins/toolbar/prism-toolbar.min.css" />' . "\n";
}
if ($options->lineNumbers) {
echo '<link rel="stylesheet" href="' . self::CDN_BASE . '/plugins/line-numbers/prism-line-numbers.min.css" />' . "\n";
}
echo '<style>
pre { position: relative; }
.line-numbers .line-numbers-rows { border-right: 1px solid #666; }
div.code-toolbar > .toolbar {
opacity: 1 !important;
top: 0.3em;
right: 0.2em;
}
div.code-toolbar > .toolbar > .toolbar-item > button {
color: #bbb;
background: rgba(255, 255, 255, 0.08);
border-radius: 4px;
padding: 4px 10px;
font-size: 12px;
box-shadow: none;
transition: all 0.2s;
}
div.code-toolbar > .toolbar > .toolbar-item > button:hover {
color: #fff;
background: rgba(255, 255, 255, 0.2);
}
.prism-fold-wrapper { position: relative; overflow: hidden; transition: max-height 0.3s ease; }
.prism-fold-mask {
position: absolute; bottom: 0; left: 0; width: 100%; height: 60px;
background: linear-gradient(to bottom, rgba(0,0,0,0), rgba(40,44,52, 0.9));
pointer-events: none; z-index: 10; display: none;
}
body:not(.dark-mode) .prism-fold-mask.light-theme {
background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255, 0.95));
}
.prism-fold-btn-wrap {
position: absolute; bottom: 10px; left: 0; width: 100%; text-align: center; z-index: 20; display: none;
}
.prism-fold-btn {
display: inline-block; padding: 6px 20px; font-size: 13px; color: #fff;
background: rgba(0,0,0,0.6); border-radius: 20px; cursor: pointer;
box-shadow: 0 2px 4px rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); user-select: none;
}
.prism-fold-btn:hover { background: rgba(0,0,0,0.8); }
.prism-expanded .prism-fold-mask { display: none !important; }
.prism-expanded .prism-fold-btn-wrap { position: static; margin-top: -20px; margin-bottom: 10px; }
</style>' . "\n";
}
public static function footer()
{
$options = Typecho_Widget::widget('Widget_Options')->plugin('SimplePrism');
$maxHeight = intval($options->maxHeight);
echo '<script src="' . self::CDN_BASE . '/prism.min.js"></script>' . "\n";
echo '<script src="' . self::CDN_BASE . '/plugins/autoloader/prism-autoloader.min.js"></script>' . "\n";
if ($options->enableCopy) {
echo '<script src="' . self::CLIPBOARD_CDN . '"></script>' . "\n";
echo '<script src="' . self::CDN_BASE . '/plugins/toolbar/prism-toolbar.min.js"></script>' . "\n";
echo '<script src="' . self::CDN_BASE . '/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>' . "\n";
}
if ($options->lineNumbers) {
echo '<script src="' . self::CDN_BASE . '/plugins/line-numbers/prism-line-numbers.min.js"></script>' . "\n";
}
echo '<script>
(function(){
var maxHeight = ' . ($maxHeight > 0 ? $maxHeight : 0) . ';
function isLightTheme() {
var theme = "' . $options->theme . '";
return theme.indexOf("tomorrow") !== -1 || theme.indexOf("default") !== -1 || theme.indexOf("solarizedlight") !== -1;
}
var pres = document.querySelectorAll("pre > code");
for (var i = 0; i < pres.length; i++) {
var pre = pres[i].parentNode;
if (pre.tagName === "PRE") {
if (!pre.classList.contains("line-numbers")) {
pre.classList.add("line-numbers");
}
pre.setAttribute("data-prismjs-copy", "复制");
pre.setAttribute("data-prismjs-copy-error", "按 Ctrl+C 复制");
pre.setAttribute("data-prismjs-copy-success", " 已复制!");
}
}
if (maxHeight > 0) {
window.addEventListener("load", function() {
var allPres = document.querySelectorAll("pre");
allPres.forEach(function(pre) {
if (pre.parentNode.classList.contains("code-toolbar")) {
var actualContainer = pre.parentNode;
if (actualContainer.scrollHeight > maxHeight + 50) {
wrapAndFold(actualContainer);
}
} else {
if (pre.scrollHeight > maxHeight + 50) {
wrapAndFold(pre);
}
}
});
});
}
function wrapAndFold(element) {
var wrapper = document.createElement("div");
wrapper.className = "prism-fold-wrapper";
wrapper.style.maxHeight = maxHeight + "px";
element.parentNode.insertBefore(wrapper, element);
wrapper.appendChild(element);
var mask = document.createElement("div");
mask.className = "prism-fold-mask";
if (isLightTheme()) mask.classList.add("light-theme");
wrapper.appendChild(mask);
mask.style.display = "block";
var btnWrap = document.createElement("div");
btnWrap.className = "prism-fold-btn-wrap";
btnWrap.style.display = "block";
var btn = document.createElement("span");
btn.className = "prism-fold-btn";
btn.innerHTML = " 展开代码 ▼";
btn.onclick = function() {
if (wrapper.classList.contains("prism-expanded")) {
wrapper.classList.remove("prism-expanded");
wrapper.style.maxHeight = maxHeight + "px";
btn.innerHTML = " 展开代码 ▼";
mask.style.display = "block";
wrapper.scrollIntoView({behavior: "smooth", block: "center"});
} else {
wrapper.classList.add("prism-expanded");
wrapper.style.maxHeight = "none";
btn.innerHTML = " 收起代码 ▲";
mask.style.display = "none";
}
};
btnWrap.appendChild(btn);
wrapper.appendChild(btnWrap);
}
})();
</script>' . "\n";
}
}
评论
还没有评论,快来抢沙发~