zyuzhi / MarkdownKatex-typecho

Typecho Plugin: Markdown Parser With Latex, Katex Support
MIT License
18 stars 0 forks source link

关于预览 #2

Open Littleor opened 3 years ago

Littleor commented 3 years ago

首先感谢能开源如此方便的插件,使用体验和效果较好,但是目前在预览界面好像并不能进行LaTeX渲染?

ccKiven1024 commented 2 years ago

首先感谢能开源如此方便的插件,使用体验和效果较好,但是目前在预览界面好像并不能进行LaTeX渲染?

我查阅了好多帖子,两种解决办法,都说可以在预览和网页中渲染数学公式:

  1. 安装或者引入MathJax支持,可以在网页前台,帖子
  2. 安装插件,比如本仓库或者MarkDown Parse之类的,帖子

但实际操作后,只能在网页中渲染,不能实时预览。 后来又发现一篇文章,有提到预览界面无法渲染LaTex:http://www.nohup.cc/article/88/ 想问一下您,经过一段时间的折腾,是否实现在预览界面渲染LaTex?或者是讲解一下不能渲染的原因

Littleor commented 2 years ago

我查阅了好多帖子,两种解决办法,都说可以在预览和网页中渲染数学公式:

  1. 安装或者引入MathJax支持,可以在网页前台,帖子
  2. 安装插件,比如本仓库或者MarkDown Parse之类的,帖子

但实际操作后,只能在网页中渲染,不能实时预览。 后来又发现一篇文章,有提到预览界面无法渲染LaTex:http://www.nohup.cc/article/88/ 想问一下您,经过一段时间的折腾,是否实现在预览界面渲染LaTex?或者是讲解一下不能渲染的原因

你好,其实这个问题并不复杂,预览没有渲染的根本原因在于渲染时没有调用对应的LaTeX解析库进行解析渲染,而在文章中的时候会将内容调用LaTeX解析库进行渲染。

具体来讲,为什么我们可以在文章中进行渲染呢?首先来看看该插件的激活配置:

    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        Typecho_Plugin::factory('Widget_Abstract_Contents')->markdown = array('MarkdownKatex_Plugin','parseDown');
        Typecho_Plugin::factory('Widget_Archive')->footer = array('MarkdownKatex_Plugin','footer');
    }

你可以看到这里做了两个插入点,一个是Widget_Abstract_Contents另一个是Widget_Archive,这里先找到Typecho源码中插件初始化的对应文件Init.php中根据对应关系找到这两个插入点对应的文件:Contents.phpArchive.php

可以看出为什么这个插件能渲染出文章的LaTeX呢?那就是这个行:

Typecho_Plugin::factory('Widget_Abstract_Contents')->markdown = array('MarkdownKatex_Plugin','parseDown');

也就是这里的markdown调用了parseDown函数进行解析做到的,具体到Content.php就是这个函数的插入点(912行):

    /**
     * markdown
     *
     * @param string|null $text
     * @return string|null
     */
    public function markdown(?string $text): ?string
    {
       $html = Contents::pluginHandle()->trigger($parsed)->markdown($text);

        if (!$parsed) {
            $html = Markdown::convert($text);
        }

        return $html;
    }

那么就很容易可以理解了,我们如果要在预览中渲染无外乎就是调用pareDown这个函数而已,但是呢我看了下插件的插入点部分没有预览这部分的,那怎么解决呢?

可能现在你认为是直接在预览的地方也调用这个方法不就行了,按道理确实如此,但是事实并非如此。

为什么呢?首先我们对预览的时候是如何解析MD进行分析,Typecho是在editor-js.php来定义的编辑器,其中就有预览功能,具体是这个包HyperDown.js实现的:

   var converter = new HyperDown(),
        editor = new Markdown.Editor(converter, '', options);

    // 自动跟随
    converter.enableHtml(true);
    converter.enableLine(true);
    reloadScroll = scrollableEditor(textarea, preview);

    // 修正白名单
    converter.hook('makeHtml', function (html) {
        html = html.replace('<p><!--more--></p>', '<!--more-->');

        if (html.indexOf('<!--more-->') > 0) {
            var parts = html.split(/\s*<\!\-\-more\-\->\s*/),
                summary = parts.shift(),
                details = parts.join('');

            html = '<div class="summary">' + summary + '</div>'
                + '<div class="details">' + details + '</div>';
        }

        // 替换block
        html = html.replace(/<(iframe|embed)\s+([^>]*)>/ig, function (all, tag, src) {
            if (src[src.length - 1] == '/') {
                src = src.substring(0, src.length - 1);
            }

            return '<div class="embed"><strong>'
                + tag + '</strong> : ' + $.trim(src) + '</div>';
        });

        return DOMPurify.sanitize(html, {USE_PROFILES: {html: true}});
    });

所以要解决这个问题并不能说通过我们的PHP模块进行解决,因为预览部分是通过HyperDown.js实现的,并不会请求后端,一切都在浏览器通过JS进行解析,然而这个插件只是做了个解析PHP的服务,所以肯定没有办法在预览中渲染啦。

事已至此,现在应该理顺了,如今相比要实现预览渲染的话其实不难,有两个大方向:

这里推荐使用第一种方法,引入MathJax这个JS的LaTeX渲染引擎即可,具体的可以自行查找对应的Doc即可,相信现在你应该可以实现预览的渲染了,期待你的作品~