Closed akabekobeko closed 3 years ago
調査メモ。
math.ts
の mdast
から Plugin
型を取り去ると this.Parser
を解決できなくなり tsc エラーPlugin
がある状態で arguments
を console.log
出力しても undefined
rehive-parse.ts
で [math: {math: enableMath}]
を指定して mdast
の引数に opts: any
を追加すると確かに受け取れたhandler
や hast
では受け取れないし、実際に数式が処理されたことの判定には利用できないhandler
の引数は h, node
のみ
VFile
がないか調べたが未指定any
で追加すると当然ながら tsc エラーhast
は第 2 引数へ VFile
を取れる
mdast
か handler
で数式処理済みフラグを指定して受け渡したいmath.ts
スコープの変数で解決を試みる。
let MATH_PROCESSED = false
を定義mdast
冒頭で必ず MATH_PROCESSED = false
を設定handler
で inlineMath
または displayMath
が処理されたら MATH_PROCESSED = true
にする、冗長になるが true
にしかならないので許容するhast
は MATH_PROCESSED = true
の場合のみタグ処理をして MATH_PROCESSED = false
を設定
handler
と hast
はセット想定なので、これらだけ実行されても矛盾しないよう念の為に初期値へ戻すmdast
もセットと考えるなら不要ではあるが ファイル スコープ変数で実際に数式を処理した場合のみ <script>
と <body>
属性の出力実行を切り替えられたので、ドキュメント修正なども含めて PR を出す。
デフォルトが有効となったため VFM の CLI オプションを --math
から --disable-math
に変更しなければならない。
CLI オプションを変更して npm link
と npm pack
で実験してみたが、なぜかビルドされたものは --disable-math
とならず古い --math
のままである。cli.ts
の変更が反映されていない。これが解決できないとリリースできないので継続調査する。
VFM のプロジェクトは npm-scripts に prepare
を指定しないため npm link
や npm pack
だけではビルドされず、事前に npm build
を実行しなくてはならない。release-it 経由のリリースだと設定は見当たらないがこれを実行してくれるようで、問題となっていなかったようだ。前も CLI のテストで同じ問題を踏んだ気がする。
npm build
後に npm link
して $x = y$
だけ記述した sample.md
を用意して
$ vfm ./sample.md
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</head>
<body data-math-typeset="true">
<p><span class="math inline">\(x = y\)</span></p>
</body>
</html>
と
$ vfm ./sample.md --disable-math
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>$x = y$</p>
</body>
</html>
をそれぞれ確認した。また数式のないものについて
$ vfm ./sample.md
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>sample</p>
</body>
</html>
のように既定で数式有効でも <script>
と <body>
の属性が出力されないことを確認した。
CLI オプション変更を確認したのでドキュメント整備してから PR する。
@akabekobeko
すみません、body 要素に data-math-typeset="true"
を指定するのは間違いだったことに気がつきました。
これは数式を直接囲む要素に指定しなくてはならないものでした。
TeX数式を含むHTMLサンプル https://github.com/jagat-xpub/cosmology の index.html の body 要素に data-math-typeset="true"
を指定して、Vivliostyle Viewer で組版結果を確認すると、ページの組版処理が正常に行われなくなってしまいました。(改ページされず1ページ目でページがオーバーフローする、など)
data-math-typeset="true"
をbody 要素にではなく、数式を囲む span 要素に出力するように変更をお願いします。例:
<span class="math inline" data-math-typeset="true">\(...\)</span>
<span class="math display" data-math-typeset="true">$$...$$</span>
もうひとつお願いです。
MathML 数式がある場合にも <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_CHTML"></script>
の出力が必要です。
MathML 数式が使われているかどうかは <math>
タグの有無で判定できるかと思います。例:
- MathML: <math><mi>x</mi><mo>=</mo><mi>y</mi></math>.
AsciiMath 対応については、今回は見合わせて、またの検討でよいかと思います。
data-math-typeset="true"
の以降は実装して PR に含めた。<math>
については以下の課題あり。
math: false
の場合でも処理するのか?<math>
タグの検出方法1 は #94 にて村上さんに問い合わせ中。2 についてまずは rehype の handler で math
をフックできるか試したがダメだった。hast で visit
によりハンドリングする場合、<script>
出力用の head
検出とどのように組み合わせるか検討する必要あり。visit
が非同期ならば同期しなければならない。hast 的に async/await 使えるのだろうか。などを調べる。
syntax-tree/hast-util-select で同期的にタグ検索できる。ただし最新版の v5.0.0 は Node.js v12 が下限となったことを踏まえてかネイティブ ESM となっているため Jest が解析できない。
FAIL tests/math.test.ts
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
これを回避するため直前の v4.0.2 を入れて math.ts
の hast
にて
const mathTag = select('math', tree);
console.log(mathTag);
を実行したら検出できた。なお match
は tree
ではなく node
対象なので select
を利用しなければならない。この関数には querySelector
と対応しており同様のセレクターを指定可能。selectAll
は querySelectorAll
に対応している。
<math>
検出による <script>
出力は VFM が math: true
の場合のみ実行するほうがよいとのこと。math: false
やそのために CLI へ --disable-math
が指定された場合は明示的な数式の無効化が期待されるため処理すべきではない。<math>
検出は math.ts
の mdast や handler ではなくユーザーが Markdown へ直に書いたものを対象とするため、hast
で VFM として math: true
なのか判定しなければならない。設計変更が必要そう。
と思ったが index.ts
にて hastMath
は math: true
時のみとしているため、新規の判定追加はしなくてよい。
hast-util-select
の select
があれば最終的な HAST から検索できる<span class="math inline" data-math-typeset="true">
などで囲むようになったことから inlineMath
と displayMath
についても select
で検索するようにすればファイル スコープ変数を無くせそう。設計的にも「状態たる変数を回避できる」のは冪等性の観点から望ましいことなので試す。
以下のように判定することでファイル スコープ変数を回避できた。PR #94 へ反映済み。
if (!(select('[data-math-typeset="true"]', tree) || select('math', tree))) {
return;
}
mdast/handler を経て生成された hast を判定するという場面は今後もありそうなので、手段として覚えておく。
Goals
37 対応により数式以外で
$
が含まれる文があっても$5
などには反応しなくなったのでmath
をデフォルト有効にしてもよいのでは?と #30 にあった。これを踏まえて対応を検討する。
Prior Art
なし
Discussion
30 に書いた私の見解を転載。
ざっと調べたメモ。
math
のデフォルト有効は容易、オプションの扱いを変更するだけでよいmath
が処理された場合のみ hast 実行は難しそうPlugin
型としているが、これの引数にVFile
を取れないようだVFile
を利用できないVFile
を取れないようだインターフェース変更して
VFile
を受け渡せるか、それともグローバル変数などの代替手段にするかを継続調査 & 検討する。