技術2025-01-07: path要素をパスカルケースにしないで!

投稿日:
技術
SVG
数学
MathML
KaTeX
MathJax

技術2025-01-07: path要素をパスカルケースにしないで!

先日、数式を使ったブログ記事を書きました。

こちら、たまに数式の表示がおかしいと思っていたら、割と頻繁におかしくなっている事に気づき、数式を読めないのはマズいと昨日今日必死でデバッグをしました。

発端は、これまで使っていたMathJax (Webページに数式を表示するためのライブラリ) で長い記事になって表示されない不具合が生じていたのと、SVG出力がSEO的に不利かもしれないという仮説のもとに改修をしたかったところで、試しにKaTeX (MathJaxよりもWebサイト向けの最適化がされているライブラリ) を導入してみたら理想の表示になったことです。

理想の表示になったかと思いきや、なんか変な不具合があるなと。

数式が正確に表示されているブログ記事のスクリーンショット
これが正しい表示
数式が正確に表示されていないブログ記事のスクリーンショット
これがバグ表示

どうも、読み込むタイミングによって平方根が消えてしまうようなのです。

バグの原因は、"√"の表示用に書き出された<path>タグが<Path>と先頭大文字(パスカルケース)になってしまい、それがおそらく厳密なSVGでないと判別されているようなのです。

<svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><Path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></Path></svg>

上記が"√"のSVG要素なのですが、正しくは <path d="M95,702...></path> なのに、 <Path d="M95,702...></Path> のようになってしまいます。

なお、表示不具合があったのは"√"に使っている<path>要素だけでしたが、SVGだけでなくMathMLのmath要素の中身も同じように先頭大文字になっています。

原因を探るのにUnified周りのライブラリを読んでみたりconsole.logを挟んだりもしましたが、一応KaTeXの出力からhastができるまでは小文字のままのようで、 本当にHTML出力をするところで余計なパスカルケースへの変換が行われてそうで、その要因まではわかりませんでした。

どこかしらでタグ名を書き換える処理ができたら、と対処法を探ったりしたのですが、困るのはNuxt (Nuxt Content v2) で

  • Unified処理が隠蔽されていて内部処理を書き換えるのが困難
  • remark / rehype 処理に既存プラグインしか入れられない(?)
  • Nuxt Contentのhooksのライフサイクルが手前部分までしか対応してない(?)

と、よしなにやってくれているところが仇となっている感じの躓きポイントがありました。

解決法

HTMLソースに手入れができなかったため、まあまあ強引ですがDOM上でSVGのinnerHTMLを置換するという方法で解決しました。

onMounted(() => {
  document.querySelectorAll('svg').forEach(svg => {
    svg.innerHTML = svg.innerHTML.replace(/<Path/g, '<path').replace(/<\/Path/g, '</path')
  })
})

SEO上は若干問題ありかもしれませんが、MathMLやSVGまではクローラには影響しないであろうというところと、ブラウザーが正しいSVGとして認識さえすればいいという割り切りで、これでとりあえず臭いものに蓋をした状態にはなりました。

しかしやはり、ライブラリのバグのように思える挙動ではあるので、また改めて原因究明をしてissueでも投げられたらなと思っています。

…せっかく新しい研究開発をしたかったのに、昨日今日の自由時間が丸潰れになってしまった。まあそれなりに勉強になったからいいけど。

著者紹介

岩淵夕希物智 butchi_y

言語を作る博士(工学)

ART, Research, Techの人