最近在用 RSS 閱讀器讀一些技術 blog,自然就產生了訂閱自己網站的想法。然而添加鏈接後發現內容不完全,在 PC 上一看才發現文章裡有一些不可見的 0x08 退格字符。刪掉之後雖然文章可見,但所有數學公式都不渲染,只顯示 TeX 代碼。

原本使用 MathJax,現在想改成 Wikipedia 那樣的圖片公式。

Math API

這一步自己不造也可以,網上有現成的。

需要一個接受 TeX 數學公式輸入並轉化成 SVG 的服務,找到 Math-API

$ docker pull chialab/math-api
$ docker run --name mathapi -p 127.0.0.1:3000:3000 -d chialab/math-api

其用的是 node.js 的 MathJax。

之後編輯 nginx.conf

location ~* ^/math/ {
        rewrite ^/math/inline/(.*)$ /render?input=latex&output=svg&inline=1&source=$1;
        rewrite ^/math/(.*)$ /render?input=latex&output=svg&source=$1;
}

location /render {
        proxy_pass http://127.0.0.1:3000;
}

Typecho 插件

不解释,直接上代碼。

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * RSS friendly LaTeX
 * 
 * @package LaTeX
 * @author tounan
 * @version 1.0.0
 * @link https://www.nottres.com
 */
class LaTeX_Plugin implements Typecho_Plugin_Interface
{
    const MATHAPI = 'https://pek1.nott.xyz:44443/math/';
    const MATHAPI_INLINE = 'https://pek1.nott.xyz:44443/math/inline/';

    public static function activate() {
        Typecho_PLugin::factory('Widget_Abstract_Contents')->content = array(__CLASS__, 'markdown');
    }
    public static function deactivate() {}
    public static function config(Typecho_Widget_Helper_Form $form){}
    public static function personalConfig(Typecho_Widget_Helper_Form $form) {}
    
    public static function markdown($mdtext) {
        $mdtext = preg_replace_callback_array(
            array(
                '/``\$(.*?)\$``/' => function ($matches) {
                    $source = preg_replace('/[\r\n]/', '', $matches[1]);
                    $alt = str_replace('\\', '\\\\', htmlspecialchars($source));
                    $url = self::MATHAPI_INLINE . str_replace('+', '%20', urlencode($source));
                    return "<img class=\"inline-math\" src=\"$url\" alt=\"$alt\" title=\"LaTeX inline math\">";
                },
                '/```latex\s+(.*?)\s+```/s' => function ($matches) {
                    $source = preg_replace('/[\r\n]/', '', $matches[1]);
                    $alt = str_replace('\\', '\\\\', htmlspecialchars($source));
                    $url = self::MATHAPI . str_replace('+', '%20', urlencode($source));
                    return "<img class=\"block-math\" src=\"$url\" alt=\"$alt\" title=\"LaTeX block math\">";
                }
            ), $mdtext);
        return Markdown::convert($mdtext);
    }
}

啟用後視情況添加樣式 .inline-math { display: inline-block; margin: 0; } 修復錯位。

測試

inline:

  1. 證明對x\ge2|\pi(x)-\mathrm{Li}(x)|\lt x\log x

block:

f(x) = \int_{-\infty}^\infty \hat f\xi\,e^{2 \pi i \xi x} \,\mathrm{d}\xi

題外話

我花了很長一段時間把舊 TeX 代碼改寫成新的(因為舊的多行公式默認左對齊,新的居中)。

另外這麼做有一個 bug,就是 iOS 深色模式時背景也是全黑的,導致一個數學公式都看不到⋯⋯