天天看點

HyperDown 擴充開發 Markdown 文法支援 MathJax問題解決方案預覽

問題

例如有這樣一段文字

$$net_{h1} = w_1 * i_1 + w_2 * i_2 + b_1 * 1$$           

公式裡面的

*

_

都可能被 markdown 文法解析。導緻最後公式無法正常解析。

解決方案

我使用的是

https://github.com/SegmentFault/HyperDown

解析器,下面對其進行一些擴充改造

單行解析處理

HyperDown 中對單行裡面的代碼片段的解析思路是:

把比對到的代碼碎片使用的是先用一個數組

$this->_holders

來存放,最後其他内容解析完畢之後再替換回來。

是以我對公式行内的解析也同樣的方式,在其

parseInline

裡面增加一個比對規則

$text = preg_replace_callback(
    "/(\\\${1,2})(.+?)\\1/",
    function ($matches) use ($self) {
        // 表達式中間的字元應該都是單位元組
        if (strlen($matches[2]) > mb_strlen($matches[2])) {
            return $matches[1] . $matches[2] . $matches[1];
        }
        return  $matches[1] . $self->makeHolder($matches[2]) . $matches[1];
    },
    $text
);           

多行的解析

參考 HyperDown 中對代碼塊的解析規則,我們可以把

$$

作為開始比對符和結束比對服,知道公式占的行是多少,然後對這個塊的代碼做自定義的處理。

首先,在

parseBlock

裡增加公式塊的比對。

// 對 TeX 或 LaTeX 公式塊的支援
if ($this->_mathJax) {
    if (preg_match("/^(\s*)\\$\\$([^\\$]*)$/i", $line, $matches)) {
        if ($this->isBlock('mathJax')) {
            $this->setBlock($key)->endBlock();
        } else {
            $this->startBlock('mathJax', $key);
        }

        continue;
    } else if ($this->isBlock('mathJax')) {
        $this->setBlock($key);
        continue;
    }
}           

然後是對應的解析規則

private function parseMathJax(array $lines){
    $str = &#39;<p>&#39;.implode(&quot;\n&quot;, $lines).&#39;</p>&#39;;
    return $str;
}           

就這麼簡單,解決了。最後位址:

https://github.com/zhoumengkang/HyperDown

預覽

https://yq.aliyun.com/articles/277312