インストール
$ npm i katex
## KaTeX の SSR
には数式表現を HTML 文字列に変換する katex.renderToString
API が用意されています。
API · KaTeX
## In-browser rendering
katex.org
以上を用いると、ヘッドレス CMS から返却された HTML など、remark/rehype を用いない場合でもプリレンダリングすることができます。
## 実装
HTML をパースするために cheerio
を利用します。
GitHub - cheeriojs/cheerio: The fast, flexible, and elegant library for parsing and manipulating HTML and XML.
The fast, flexible, and elegant library for parsing and manipulating HTML and XML. - cheeriojs/cheerio
github.com
インストール
$ npm i cheerio
初期化
import { load } from "cheerio";
// CMS から返ってきた HTML 文字列で初期化する
let $ = load(html);
### レンダリング処理
デリミタ(区切り文字)で囲われた部分の文字列のみレンダリングするようにします。インラインであれば $
、別行立てには $$
を用います。
インラインと別行立てのデリミタがバッティングしないように、正規表現では任意の文字列 .+
の代わりに [^\$]+
を用います。
また、先に別行立てをレンダリングすることで、別行立てがインラインとしてレンダリングされることを防ぎます。
TypeScript
import katex from "katex";
// 先に別行立てをレンダリング
const renderedDisplayText = $.html().replaceAll(/\$\$[^\$]+\$\$/g, (text: string) => {
return katex.renderToString(text.replaceAll("$", "").replaceAll(/(<br>|<\\br>|<br \/>| |amp;)/g, ""), { output: "html", displayMode: true });
});
// インラインをレンダリング
const renderedText = renderedDisplayText.replaceAll(/\$[^\$]+\$/g, (text: string) => {
return katex.renderToString(text.replaceAll("$", "").replaceAll(/(<br>|<\\br>|<br \/>| |amp;)/g, ""), { output: "html", displayMode: false });
});
### code タグのエスケープ
<code>
内のテキストはデリミタとなる $
が使用される可能性が高く、しかもレンダリングされると困ります。Cheerioを利用して <code>
でラップされたテキストを取り出し、一時的に保持してレンダリング後に差し戻す処理を実装します。
TypeScript
// <code> のテキストを抽出
const innerTexts: string[] = [];
$("code").each((_, elm) => {
innerTexts.push($(elm).text());
$(elm).text("");
});
/*
* レンダリング
*/
// 再び初期化
$ = load(renderedText);
// <code>にテキストを差し戻す
$("code").each((idx, elm) => {
$(elm).text(innerTexts[idx]);
});
### HTML をレンダリング
Astro
---
import "katex/dist/katex.min.css"; // CSS
/*
* レンダリング
*/
const renderedHtml = $.html();
---
<div set:html={renderedHtml} />
## CSRによる実装
以上の実装は の Auto-render Extension↗ を代わりに使うことで簡単に達成できます。
Astroの場合、Client で 処理する JS は <script>
内に記述します。
src/pages/article/[slug].astro
---
// .....
---
<script>
import { renderMathInElement } from "katex/dist/contrib/auto-render";
document.addEventListener("DOMContentLoaded", () => {
renderMathInElement(document.body, {
delimiters: [
{ left: '$$', right: '$$', display: true },
{ left: '$', right: '$', display: false },
{ left: '\\(', right: '\\)', display: false },
{ left: '\\[', right: '\\]', display: true },
],
ignoredTags: ["code"],
});
});
</script>
## Usage
TeX
$$
\lim_{n \to \infty} \frac{1}{n} \sum_{k=0}^{n-1} f \left( \frac{k}{n} \right) = \int_{0}^{1} f(x) dx
$$
記事がありません