[ Jekyll  ]

如何在博客中插入算法伪代码

最近写博客比较频繁,有需要插入伪代码的场景。我本身写博客的流程是用 Typora 写 Markdown + Jekyll 渲染生成静态网站,可惜它们都不支持像 $\LaTeX$ 那样的伪代码。经过一番摸索,我自己找到一个解决方案,还算比较简单。

如果你也用 Typora 和 Jekyll,则可以直接应用我的步骤。其他情况也可作参考。

下面是效果:

% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)
\begin{algorithm}
\caption{Quicksort}
\begin{algorithmic}
\PROCEDURE{Quicksort}{$A, p, r$}
    \IF{$p < r$} 
        \STATE $q = $ \CALL{Partition}{$A, p, r$}
        \STATE \CALL{Quicksort}{$A, p, q - 1$}
        \STATE \CALL{Quicksort}{$A, q + 1, r$}
    \ENDIF
\ENDPROCEDURE
\PROCEDURE{Partition}{$A, p, r$}
    \STATE $x = A[r]$
    \STATE $i = p - 1$
    \FOR{$j = p$ \TO $r - 1$}
        \IF{$A[j] < x$}
            \STATE $i = i + 1$
            \STATE exchange
            $A[i]$ with     $A[j]$
        \ENDIF
        \STATE exchange $A[i]$ with $A[r]$
    \ENDFOR
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}

1. Dependencies

我借用的是一个 JS 库,叫做 Pseudocode.js,它能将 $\LaTeX$ 里的 algorithm 环境渲染到网页。当然还需要 jQuery

2. 原理

Typora 本身支持语言为 pseudocode 的代码块,但是 Jekyll 无法渲染它。因此可以借用它来存放伪代码,然后用 Pseudocode.js 渲染里面的伪代码。

3. 配置步骤

在网页头 _includes/head.html 模板中加入所需脚本和 CSS:

<link rel="stylesheet" href="/assets/pseudocode.min.css">
<script src="/assets/pseudocode.min.js"></script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css"
    integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ" crossorigin="anonymous">

<script src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js"
    integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij"
    crossorigin="anonymous"></script>

<script src="https://code.jquery.com/jquery-3.4.0.min.js"></script>

注意:KaTeX 是 Pseudocode.js 的依赖。

在网页尾加入 JavaScript 代码做下面几件事:

  1. 找到 .language-pseudocode 类的元素
  2. 用 Pseudocode.js 来渲染里面的代码
  3. 修改 DOM 并将原代码删除

JavaScript 代码如下:

let pseudocodes = document.querySelectorAll(".language-pseudocode");
let options = {
    lineNumber: true
};
pseudocodes.forEach((pse) => {
    let code = pse.textContent;
    let parentEl = pse.parentElement;
    pseudocode.render(code, parentEl, options);
    pse.remove();
    $(parentEl).replaceWith($('<div>' + parentEl.innerHTML + '</div>'));
})

4. 使用方法

打开 Typora,用 pseudocode 代码块写一段 LaTeX 伪代码,比如:

% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)
\begin{algorithm}
\caption{Quicksort}
\begin{algorithmic}
\PROCEDURE{Quicksort}{$A, p, r$}
    \IF{$p < r$} 
        \STATE $q = $ \CALL{Partition}{$A, p, r$}
        \STATE \CALL{Quicksort}{$A, p, q - 1$}
        \STATE \CALL{Quicksort}{$A, q + 1, r$}
    \ENDIF
\ENDPROCEDURE
\PROCEDURE{Partition}{$A, p, r$}
    \STATE $x = A[r]$
    \STATE $i = p - 1$
    \FOR{$j = p$ \TO $r - 1$}
        \IF{$A[j] < x$}
            \STATE $i = i + 1$
            \STATE exchange
            $A[i]$ with     $A[j]$
        \ENDIF
        \STATE exchange $A[i]$ with $A[r]$
    \ENDFOR
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}

然后,就大功告成了!用 Jekyll build 后会发现,它就是本文最上面伪代码的源码。

(本文完)

我发现它没有支持 REPEAT...UNTIL 这种循环,于是自己 fork 了它的仓库,把这个加上了。这也是我的网站现在用的版本。

4 月 28 日:它的仓库已经 merge 了我的 PR,所以现在它也支持 repeat 了 : )