站点描述将显示在网页代码的头部.

代码高亮

<?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 = " 展开代码 &#9660;";
                
                btn.onclick = function() {
                    if (wrapper.classList.contains("prism-expanded")) {
                        wrapper.classList.remove("prism-expanded");
                        wrapper.style.maxHeight = maxHeight + "px";
                        btn.innerHTML = " 展开代码 &#9660;";
                        mask.style.display = "block";
                        wrapper.scrollIntoView({behavior: "smooth", block: "center"});
                    } else {
                        wrapper.classList.add("prism-expanded");
                        wrapper.style.maxHeight = "none";
                        btn.innerHTML = " 收起代码 &#9650;";
                        mask.style.display = "none";
                    }
                };
                
                btnWrap.appendChild(btn);
                wrapper.appendChild(btnWrap);
            }
        })();
        </script>' . "\n";
    }
}

评论

还没有评论,快来抢沙发~