Skip to content

Commit

Permalink
Merge pull request #49 from mrgeneralgoo/2.0
Browse files Browse the repository at this point in the history
Fix rendering issues with MathJax and Mermaid, and add support for configuring mermaid themes
  • Loading branch information
mrgeneralgoo authored Jan 27, 2024
2 parents 13dc08b + 0597937 commit 284f610
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 18 deletions.
35 changes: 31 additions & 4 deletions MarkdownParse.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
use Wnx\CommonmarkMarkExtension\MarkExtension;
use League\CommonMark\Extension\DefaultAttributes\DefaultAttributesExtension;
use SimonVomEyser\CommonMarkExtension\LazyImageExtension;
use League\CommonMark\Event\DocumentPreRenderEvent;
use League\CommonMark\Node\Node;
use League\CommonMark\Node\Query;
use League\CommonMark\Node\Inline\Text;

class MarkdownParse
{
Expand Down Expand Up @@ -77,6 +81,24 @@ public function parse(string $text, array $config = []): string

$environment = new Environment(array_merge($this->getConfig(), $config));

$environment->addEventListener(DocumentPreRenderEvent::class, function (DocumentPreRenderEvent $event) {
$document = $event->getDocument();
$matchingNodes = (new Query())
->where(Query::type(FencedCode::class))
->andWhere(function (Node $node): bool {
return $node->getInfo() === 'mermaid';
})
->findAll($document);

foreach ($matchingNodes as $node) {
$divNode = new Text('<div class="' . $node->getInfo() . '">' . $node->getLiteral() . '</div>');
// foreach ($node->children() as $child) {
// $divNode->appendChild($child);
// }
$node->replaceWith($divNode);
}
});

$this->addCommonMarkExtensions($environment);

$htmlContent = (new MarkdownConverter($environment))->convert($text)->getContent();
Expand Down Expand Up @@ -107,13 +129,13 @@ public function preParse(string $text, array $config = []): array

// Check if LaTeX is needed by searching for $$ or $ in the text
if (!$this->isNeedLaTex) {
$this->isNeedLaTex = (bool) preg_match('/\${1,2}[^`]*?\${1,2}/m', $text);
$this->isNeedLaTex = (bool)preg_match('/\${1,2}[^`]*?\${1,2}/m', $text);
}

// Replace double $$ at the beginning and end of the text with <div> tags
$count = 0;
$text = preg_replace('/(^\${2,})(.*)(\${2,}$)/ms', '<div>$1$2$3</div>', $text, -1, $count);
$this->isNeedLaTex = $this->isNeedLaTex || $count > 0;
if ($this->isNeedLaTex) {
$text = preg_replace('/(^\${2,})([\s\S]+?)(\${2,})/m', '<div>$1$2$3</div>', $text, -1);
}

return [$text, $config];
}
Expand All @@ -127,6 +149,8 @@ public function preParse(string $text, array $config = []): array
*/
public function postParse(string $htmlContent, array $config = []): array
{
$htmlContent = htmlspecialchars_decode($htmlContent);

// If LaTeX is needed, remove <div> tags added during preParse
if ($this->isNeedLaTex) {
$htmlContent = str_replace(['<div>$$', '$$</div>'], '$$', $htmlContent);
Expand All @@ -153,6 +177,9 @@ public function getConfig(): array
'internal_hosts' => [],
'open_in_new_window' => true,
],
'heading_permalink' => [
'symbol' => '',
],
'default_attributes' => [
FencedCode::class => [
'class' => static function (FencedCode $node) use ($instance) {
Expand Down
31 changes: 17 additions & 14 deletions Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* @author mrgeneral
* @package MarkdownParse
* @version 2.0.0
* @version 2.1.0
* @link https://www.chengxiaobai.cn/
*/
class Plugin implements PluginInterface
Expand All @@ -24,10 +24,10 @@ class Plugin implements PluginInterface

const CDN_SOURCE_DEFAULT = 'jsDelivr';
const CDN_SOURCE_MERMAID = [
'jsDelivr' => 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js',
'cdnjs' => 'https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.min.js',
'baomitu' => 'https://lib.baomitu.com/mermaid/latest/mermaid.min.js',
'bootcdn' => 'https://cdn.bootcdn.net/ajax/libs/mermaid/10.7.0/mermaid.min.js'
'jsDelivr' => 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs',
'cdnjs' => 'https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs',
'baomitu' => 'https://lib.baomitu.com/mermaid/10.7.0/mermaid.esm.min.mjs',
'bootcdn' => 'https://cdn.bootcdn.net/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs'
];
const CDN_SOURCE_MATHJAX = [
'jsDelivr' => 'https://cdn.jsdelivr.net/npm/mathjax/es5/tex-mml-chtml.min.js',
Expand Down Expand Up @@ -56,13 +56,16 @@ public static function config(Form $form)
$elementMermaid = new Form\Element\Radio('is_available_mermaid', [self::RADIO_VALUE_DISABLE => _t('不开启'), self::RADIO_VALUE_AUTO => _t('开启(按需加载)'), self::RADIO_VALUE_FORCE => _t('开启(每次加载,pjax 主题建议选择此选项)')], self::RADIO_VALUE_AUTO, _t('是否开启 Mermaid 支持(支持自动识别,按需渲染,无需担心引入冗余资源)'), _t('开启后支持解析并渲染 <a href="https://mermaid-js.github.io/mermaid/#/">Mermaid</a>'));
$form->addInput($elementMermaid);

$elementMermaidTheme = new Form\Element\Radio('mermaid_theme', ['default' => _t('默认(default)'), 'neutral' => _t('墨水(neutral)'), 'dark' => _t('暗黑(dark)'), 'forest' => _t('森林绿(forest)')], 'default', _t('Mermaid 主题颜色'), _t('可以去这里 <a href="https://mermaid.live/edit">实时编辑器</a>调整主题配置看下效果'));
$form->addInput($elementMermaidTheme);

$elementMathJax = new Form\Element\Radio('is_available_mathjax', [self::RADIO_VALUE_DISABLE => _t('不开启'), self::RADIO_VALUE_AUTO => _t('开启(按需加载)'), self::RADIO_VALUE_FORCE => _t('开启(每次加载,pjax 主题建议选择此选项)')], self::RADIO_VALUE_AUTO, _t('是否开启 MathJax 支持(支持自动识别,按需渲染,无需担心引入冗余资源)'), _t('开启后支持解析并渲染 <a href="https://www.mathjax.org/">MathJax</a>'));
$form->addInput($elementMathJax);

$elementCDNSource = new Form\Element\Radio('cdn_source', array_combine(array_keys(self::CDN_SOURCE_MERMAID), array_map('_t', array_keys(self::CDN_SOURCE_MERMAID))), self::CDN_SOURCE_DEFAULT);
$elementCDNSource = new Form\Element\Radio('cdn_source', array_combine(array_keys(self::CDN_SOURCE_MERMAID), array_map('_t', array_keys(self::CDN_SOURCE_MERMAID))), self::CDN_SOURCE_DEFAULT, _t('静态资源 CDN'), _t('jsDelivr 默认使用最新版本'));
$form->addInput($elementCDNSource);

$elementInternalHosts = new Form\Element\Text('internal_hosts', null, parse_url(Options::alloc()->siteUrl(), PHP_URL_HOST), _t('设置内部链接'), _t('默认为本站点地址,支持正则表达式("/(^|\.)example\.com$/"),多个可用英文逗号分隔。外部链接解析策略:默认在新窗口中打开,并加上 "noopener noreferrer" 属性'));
$elementInternalHosts = new Form\Element\Text('internal_hosts', null, '', _t('设置内部链接'), _t('默认为本站点地址,支持正则表达式("/(^|\.)example\.com$/"),多个可用英文逗号分隔。<br/>外部链接解析策略:默认在新窗口中打开,并加上 "noopener noreferrer" 属性'));
$form->addInput($elementInternalHosts);

$elementHelper = new Form\Element\Radio('show_help_info', [], self::RADIO_VALUE_DISABLE, _t('<a href="https://www.chengxiaobai.cn/php/markdown-parser-library.html/">点击查看更新信息</a>'), _t('<a href="https://www.chengxiaobai.cn/record/markdown-concise-grammar-manual.html/">点击查看语法手册</a>'));
Expand All @@ -79,31 +82,31 @@ public static function parse($text)
$markdownParser = MarkdownParse::getInstance();

$markdownParser->setIsTocEnable((bool)Options::alloc()->plugin('MarkdownParse')->is_available_toc);
$markdownParser->setInternalHosts((string)Options::alloc()->plugin('MarkdownParse')->internal_hosts);
$markdownParser->setInternalHosts((string)Options::alloc()->plugin('MarkdownParse')->internal_hosts ?: parse_url(Options::alloc()->siteUrl, PHP_URL_HOST));

return $markdownParser->parse($text);
}

public static function resourceLink()
{
$markdownParser = MarkdownParse::getInstance();
$configMermaid = (int)Options::alloc()->plugin('MarkdownParse')->is_available_mermaid;
$configLaTex = (int)Options::alloc()->plugin('MarkdownParse')->is_available_mathjax;
$configCDN = (string)Options::alloc()->plugin('MarkdownParse')->cdn_source;
$markdownParser = MarkdownParse::getInstance();
$isAvailableMermaid = $configMermaid === self::RADIO_VALUE_FORCE || ($markdownParser->getIsNeedMermaid() && $configMermaid === self::RADIO_VALUE_AUTO);
$isAvailableMathjax = $configLaTex === self::RADIO_VALUE_FORCE || ($markdownParser->getIsNeedLaTex() && $configLaTex === self::RADIO_VALUE_AUTO);

$resourceContent = '';
$resourceContent = '';

if ($isAvailableMermaid) {
$resourceContent .= '<script type="text/javascript">function initMermaid(){mermaid.initialize({startOnLoad:true})}</script>';
$resourceContent .= sprintf('<script async defer type="text/javascript" src="%s"></script>', !empty(self::CDN_SOURCE_MERMAID[$configCDN]) ? self::CDN_SOURCE_MERMAID[$configCDN] : self::CDN_SOURCE_MERMAID[self::CDN_SOURCE_DEFAULT]);
$resourceContent .= sprintf('<script type="module">import mermaid from "%s";',self::CDN_SOURCE_MERMAID[$configCDN] ?: self::CDN_SOURCE_MERMAID[self::CDN_SOURCE_DEFAULT]);
$resourceContent .= sprintf('mermaid.initialize({ startOnLoad: true,theme:"%s"});</script>', (string)Options::alloc()->plugin('MarkdownParse')->mermaid_theme ?: 'default');
}

if ($isAvailableMathjax) {
$resourceContent .= '<script type="text/javascript">(function(){MathJax={tex:{inlineMath:[[\'$\',\'$\'],[\'\\\\(\',\'\\\\)\']]}}})();</script>';
$resourceContent .= '<script async defer src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>';
$resourceContent .= sprintf('<script id="MathJax-script" async defer type="text/javascript" src="%s"></script>', !empty(self::CDN_SOURCE_MATHJAX[$configCDN]) ? self::CDN_SOURCE_MATHJAX[$configCDN] : self::CDN_SOURCE_MATHJAX[self::CDN_SOURCE_DEFAULT]);
$resourceContent .= '<script defer src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>';
$resourceContent .= sprintf('<script id="MathJax-script" defer type="text/javascript" src="%s"></script>', self::CDN_SOURCE_MATHJAX[$configCDN] ?: self::CDN_SOURCE_MATHJAX[self::CDN_SOURCE_DEFAULT]);
}

echo $resourceContent;
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ MarkdownParse 是一款基于 [league/commonmark](https://commonmark.thephpleagu
2. 修改文件夹的名字为 "MarkdownParse"
3. 添加到你的项目中并启用它

## 配置页面

![MarkdownParse Config Page](./markdown-parse-config-page.png)

## 报告问题

[你可以直接点击这里提出你的问题](https://github.com/mrgeneralgoo/typecho-markdown/issues/new)
Expand Down Expand Up @@ -53,6 +57,10 @@ In addition to the functions mentioned in the CommonMark and GFM specifications
2. Rename the folder to "MarkdownParse"
3. Add it to your project and activate it

## Configuration

![MarkdownParse Config Page](./markdown-parse-config-page.png)

## Reporting Issues

[You can click here directly to create an issue](https://github.com/mrgeneralgoo/typecho-markdown/issues/new)
Expand Down
Binary file added markdown-parse-config-page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 284f610

Please sign in to comment.