問題
例如有這樣一段文字
$$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 = '<p>'.implode("\n", $lines).'</p>';
return $str;
}
就這麼簡單,解決了。最後位址:
https://github.com/zhoumengkang/HyperDown