JavaScript を使用してブラウザ上に数式を表示する代表的なライブラリに KaTeX と MathJax があります。今回は両方の実装方法を解説していきます。
KaTeX を使用するのに前回使用した Marked を利用するので、ソースコードは前回の記事のものを流用します。
完成しているコードは下記にあります。
環境
- node: 18.20.0
- Angular CLI:17.0.0
- Marked:14.1.3
- marked-katex-extension:5.1.2
- mathjax-angular:2.2.1
KaTeX
パッケージのインストール
$ npm install marked
$ npm install marked-katex-extension
ライブラリは Marked を使って簡単に KaTeX が使える marked-katex-extension を使用します。
スタイルシートのインポート
@import 'katex/dist/katex.min.css';
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
コンポーネントの生成
$ ng generate component component/page/katex
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { InputComponent } from '../../share/input/input.component';
import { OutputComponent } from '../../share/output/output.component';
import { marked } from 'marked';
import markedKatex from "marked-katex-extension";
@Component({
selector: 'app-katex',
standalone: true,
imports: [InputComponent, OutputComponent],
templateUrl: './katex.component.html',
styleUrl: './katex.component.css'
})
export class KatexComponent {
public safeHTML!: SafeHtml;
private readonly KATEX_OPTIONS = {
throwOnError: false
};
constructor(
private sanitizer: DomSanitizer
) {
marked.use(markedKatex(this.KATEX_OPTIONS));
}
public async onParse(message: any) {
const content = await marked.parse(message);
this.safeHTML = this.sanitizer.bypassSecurityTrustHtml(content);
}
}
26行目
marked.use(markedKatex(this.KATEX_OPTIONS))
と設定するだけで Marked と同じ要領で KaTeX が使えるようになります。
確認
入力は数式を「$」で囲むとインラインとして、「$$」で囲むとブロックとして出力されます。
This is inline katex: $c = \pm\sqrt{a^2 + b^2}$
$$
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
$$

MathJax
パッケージのインストール
$ npm install mathjax-angular
ライブラリは Angular で簡単に MathJax が使用できる mathjax-angular を使用します。変にこだわらなければ楽に数式を出力できます。ただ、今回は変にこだわってるのでかなり苦労しました・・・
モジュールの生成
$ ng generate module modules/mathjax-root
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MathjaxModule } from 'mathjax-angular';
const MATHJAX_CONFIG = {
config: {
loader: {
load: ["output/svg", "[tex]/require", "[tex]/ams"]
},
tex: {
inlineMath: [["$", "$"], ["\\(", "\\)"]],
displayMath: [["$$", "$$"], ["\\[", "\\]"]],
packages: ["base", "require", "ams"]
},
},
src: "https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/startup.js"
};
@NgModule({
declarations: [],
imports: [
CommonModule,
MathjaxModule.forRoot(MATHJAX_CONFIG)
]
})
export class MathjaxRootModule { }
MathJax の設定をするためのモジュールを生成します。Angular16以前で app.module.ts
があればそっちで記載したほうがいいです。
公式の GitHub で解説されてる設定に追加して、 displayMath
を設定することでブロック単位で数式に変換できるようにしています。
コンポーネントの生成
$ ng generate component component/page/mathjax
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { MatCardModule } from '@angular/material/card';
import { InputComponent } from '../input/input.component';
import { OutputComponent } from '../output/output.component';
import { MathjaxRootModule } from '../modules/mathjax-root/mathjax-root.module'
declare global {
interface Window {
MathJax: any;
}
}
@Component({
selector: 'app-mathjax',
standalone: true,
imports: [MatCardModule, InputComponent, OutputComponent, MathjaxRootModule],
templateUrl: './mathjax.component.html',
styleUrl: './mathjax.component.css'
})
export class MathjaxComponent {
public safeHTML!: SafeHtml;
public content: string = '';
constructor(
private sanitizer: DomSanitizer
) { }
public async onParse(message: any) {
let content = '<div class="math-content">' + message + '</div>';
this.safeHTML = this.sanitizer.bypassSecurityTrustHtml(content);
setTimeout(() => {
const math = document.querySelectorAll('.math-content');
if (math && window.MathJax) {
window.MathJax.typesetPromise(math);
}
}, 0);
}
}
本来であれば HTML に <div [mathjax]="content"></div>
と記載しておき、 TypeScript から content
に数式を代入すれば簡単に数式を表示することができます。ただ今回は、 KaTeX とアウトプットの方法を変更したくないという変なこだわりにより、変に凝った作りにしています。
9~13行目
手動で MathJax
を操作したいので、ブラウザの Window
インターフェースに MathJax
プロパティを追加しています。本来であれば不要です。
33~38行目
safeHTML
が DOM に反映されるのを待ってから、 window.MathJax.typesetPromise()
で数式をレンダリングします。引数に DOM を渡すとその DOM のみに MathJax のレンダリングが反映されます。引数を渡さない場合は、ページ全体に反映されます。これも本来であれば不要です。
確認
KaTeX と同じように、数式を「$」で囲むとインラインとして、「$$」で囲むとブロックとして出力されます。
This is inline katex: $c = \pm\sqrt{a^2 + b^2}$
$$
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
$$

KaTeX と MathJax の比較
KaTeX も MathJax もできることは同じですが、何が違うのかというと出力する方式が違います。KaTeX は HTML で出力されて、 MathJax は(設定にもよりますが)svg で出力されます。
今回は解説のため両方紹介しましたが、 KaTeX の方が高速なので基本的には KaTeX を使えば問題ないです。
コメント