0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django学習記録⑦今日実装した機能:数式(KaTeX)対応

0
Posted at

はじめに

今日は、開発中のメモ管理アプリ「SmartMemo」にKaTeXによる数式表示機能を実装しました。

これまでSmartMemoではMarkdownに対応し、CodeMirrorを使った編集やリアルタイムプレビューを実装してきました。

今回はさらに、Markdownの中に数式を記述できるようにし、

$...$ によるインライン数式
$$...$$ による独立した数式

を表示できるようにしました。

1. KaTeXを導入

まず、KaTeXに必要なファイルをCDNから読み込みました。

katex.min.css
katex.min.js
auto-render.min.js

KaTeXを利用することで、例えば次のような記述を数式として表示できます。

$E = mc^2$

また、独立した数式として、

$$
\int_0^1 x^2 dx = \frac{1}{3}
$$

のような記述にも対応しました。

2. 入力中のリアルタイムプレビューにKaTeXを反映

次に、メモ作成画面と編集画面のリアルタイムプレビューにも数式表示を追加しました。

対象となるのは、

create.html
edit.html

です。

SmartMemoでは、入力したMarkdownをJavaScriptで変換してプレビューしています。

そこで、updatePreview() の中で、

今回の処理の流れは、

Markdown変換(marked.js)

DOMPurifyでサニタイズ(XSS対策)

KaTeXによる数式レンダリング

プレビュー表示

という流れにしました。

ポイントは、renderMathInElement() をプレビュー更新処理の中で呼び出すことです。

これにより、入力内容が変更されるたびにMarkdownと数式の表示も更新されるようになりました。

また、このタイミングでCodeMirrorのテーマをdraculaからmonokaiへ変更しました。

3. 保存済みメモにもKaTeXを反映

入力中だけでなく、保存したメモの詳細画面でも数式を表示できるようにしました。

対象は、

detail.html

です。

ページ読み込み時に、

document.addEventListener("DOMContentLoaded", ...)

を利用してKaTeXのレンダリングを実行するようにしました。

これにより、

入力

リアルタイムプレビュー

保存

詳細画面

という一連の流れで数式を表示できるようになりました。

なお、一覧画面のindex.htmlは現在「タイトル+更新日」の表示のみとしているため、メモ本文を表示していません。

そのため、今回は一覧画面へのKaTeX対応は見送ることにしました。

4. 実装中にハマったポイント

今回、一番勉強になったのがrenderMathInElement()をどこで実行するかという問題でした。

最初は、renderMathInElement()をプレビュー更新関数の外に書いていました。

そのため、ページの初回読み込み時には数式が表示されるものの、その後入力内容を変更しても数式が更新されませんでした。

原因は、updatePreview()が入力のたびに呼ばれているのに対して、KaTeXのレンダリング処理は最初の1回しか実行されていなかったことでした。

そこで、

updatePreview()

Markdown変換

サニタイズ

renderMathInElement()

という形に変更しました。

今回のことで、**「処理を関数の中に書くのか、外に書くのかによって実行されるタイミングが変わる」**ということを実感しました。

5. JavaScript側とPython側の役割

今回もう一つ学んだのが、リアルタイムプレビューと保存後の表示では処理の仕組みが異なるということです。

SmartMemoでは、Markdownの処理にPythonのmarkdownライブラリとbleachを使用しています。

しかし、PythonのMarkdownライブラリ自体はLaTeXの数式を描画するものではありません。

そのため、今回は、

入力中
JavaScript + Markdown + KaTeX

リアルタイムプレビュー

保存後
Python + Markdown + Bleach

HTML生成

ブラウザ側でKaTeX

数式表示

という役割分担にしました。

数式そのものをPython側で変換するのではなく、数式の描画はブラウザ側のKaTeXに任せるという設計です。

6. タイトル未入力で保存できてしまうバグを修正

KaTeXの実装とは別に、今回の開発中に一つバグを発見しました。

タイトルとカテゴリを入力せずに保存したところ、タイトルが空のメモが作成されてしまいました。

その結果、一覧画面ではタイトルが表示されないため、詳細画面へ移動するリンクもクリックできない「見えないメモ」のような状態になりました。

そこで、タイトルを必須項目として扱うように修正しました。

views.pyのcreateビューに空欄チェックを追加し、create.htmlにはエラーメッセージを表示するようにしました。

また、すでに作成されてしまった空タイトルのメモについては、Django Adminから削除して対応しました。

今回のように、実際にアプリを使ってみることで、想定していなかった入力パターンによるバグを発見できました。

今回学んだこと

今回の実装を通して、以下のことを学びました。

KaTeXによるLaTeX数式の表示方法
auto-render.min.jsによる自動レンダリング
リアルタイムプレビューと数式レンダリングの組み合わせ
JavaScriptの関数が実行されるタイミング
JavaScript側とPython側の役割分担
MarkdownとLaTeXは別の仕組みであること
入力値のバリデーションの重要性
実際にアプリを操作してバグを発見することの大切さ
今後の予定

SmartMemoは、単なるメモ管理アプリではなく、

「メモ Write・コード Code・実行 Run」

を一つの場所で管理できるアプリを目指しています。

今後はさらに、

  • コード編集機能の改善
  • コード実行機能
  • AIアシスタント機能
  • PostgreSQL対応
  • UI改善

などにも取り組んでいく予定です。

少しずつですが、Djangoを学びながらSmartMemoを成長させていきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?