Typecho插件:增强渲染MarkdownPlus

简单介绍

MarkdownPlus是让Codex通过本站主题HansJack文章的渲染功能来剥离而出的Typecho插件,不确保你的主题能不能完美适配,不过添加了主题文章内容选中器。

主要功能

  • 提示块(alert)和引用块增强

[!NOTE]
111

[!TIP]
111

[!IMPORTANT]
111

[!WARNING]
111

[!CAUTION]
111

并且支持折叠。

  • 行内语法增强

剧透插入高亮注音

  • 嵌入短代码

{% youtube %}、{% bilibili %}、{% video %}、{% iframe/embed %}、{% comment %}

  • Onebox 卡片

段落里单独 URL 自动卡片化;GitHub repo/issue/PR 会调用 GitHub API 补全信息

https://github.com/VintageStory-Community/vintagestory-forum-cn

无法读取该文件内容。
  • 图片增强

独立图片段落转 figure + figcaption,并自动 loading="lazy"

图片

  • 代码块增强

复制按钮、超过 10 行可折叠

class Plugin implements PluginInterface
{
    private const VERSION = '1.0.2';
    private static $frontRendered = false;

    public static function activate()
    {
        \Typecho\Plugin::factory('Widget_Archive')->footer = [__CLASS__, 'renderFooter'];
        return _t('MarkdownPlus 已启用');
    }

    public static function deactivate()
    {
    }

    public static function config(Form $form)
    {
        $selector = new Text(
            'contentSelector',
            null,
            '.post-content, .post_content',
            _t('文章内容容器选择器'),
            _t('支持多个 CSS 选择器,使用英文逗号分隔。留空时默认匹配 default / OneBlog 的正文容器。')
        );
        $form->addInput($selector);
    }

    public static function personalConfig(Form $form)
    {
    }

    private static function cut($text, $len)
    {
        if (function_exists('mb_substr')) {
            return mb_substr((string) $text, 0, (int) $len);
        }
        return substr((string) $text, 0, (int) $len);
    }

    private static function getConfig()
    {
        $defaults = [
            'contentSelector' => '.post-content, .post_content',
        ];

        try {
            $raw = \Helper::options()->plugin('MarkdownPlus')->toArray();
            if (!is_array($raw)) {
                $raw = [];
            }
        } catch (\Throwable $e) {
            $raw = [];
        }

        $cfg = array_merge($defaults, $raw);
        $selector = trim((string) ($cfg['contentSelector'] ?? ''));
        $selector = str_replace(["\r\n", "\r", "\n"], ' ', $selector);
        $selector = preg_replace('/\s{2,}/u', ' ', $selector);
        $selector = trim((string) $selector);
        if ($selector === '') {
            $selector = $defaults['contentSelector'];
        }
        $cfg['contentSelector'] = self::cut($selector, 600);

        return $cfg;
    }

    public static function renderFooter($archive)
    {
        if (defined('__TYPECHO_ADMIN__') && __TYPECHO_ADMIN__) {
            return;
        }

        if (self::$frontRendered) {
            return;
        }

        if (!is_object($archive) || !method_exists($archive, 'is')) {
            return;
        }

        $isSingle = false;
        try {
            $isSingle = $archive->is('single') || $archive->is('post') || $archive->is('page');
        } catch (\Throwable $e) {
            $isSingle = false;
        }
        if (!$isSingle) {
            return;
        }

        $cfg = self::getConfig();

        $pluginUrl = '';
        try {
            $pluginUrl = rtrim((string) (\Helper::options()->pluginUrl ?? ''), '/') . '/MarkdownPlus';
        } catch (\Throwable $e) {
            $pluginUrl = '';
        }
        if ($pluginUrl === '') {
            return;
        }

        $bootstrap = [
            'version' => self::VERSION,
            'contentSelector' => (string) ($cfg['contentSelector'] ?? ''),
            'assetBase' => $pluginUrl . '/assets',
        ];

        $json = json_encode(
            $bootstrap,
            JSON_UNESCAPED_UNICODE
            | JSON_UNESCAPED_SLASHES
            | JSON_HEX_TAG
            | JSON_HEX_AMP
            | JSON_HEX_APOS
            | JSON_HEX_QUOT
        );
        if ($json === false) {
            return;
        }

        self::$frontRendered = true;

        echo '<link rel="stylesheet" href="'
            . htmlspecialchars($pluginUrl . '/assets/markdown-plus.css?v=' . self::VERSION, ENT_QUOTES, 'UTF-8')
            . '">';
        echo '<script type="application/json" id="markdownplus-config">' . $json . '</script>';
        echo '<script src="'
            . htmlspecialchars($pluginUrl . '/assets/markdown-plus.js?v=' . self::VERSION, ENT_QUOTES, 'UTF-8')
            . '" defer></script>';
    }
}
  • 图表/白板渲染

支持 vega-lite 和 excalidraw 代码块

  • 移动端交互优化

tooltip/spoiler 点击展开逻辑

本文采用 CC BY-NC-SA 4.0 进行许可。

猜你想看

评论 4
  1. 懋和道人的头像
    懋和道人

    ❤️宝贝辛苦了。

  2. 無境的头像
    無境

    感觉很强大,现在原来还有很多还在使用 typecho