hygenでejs文法エラーの位置を指摘するようにする
結論:
code:example.txt
hogehogehogehoge
~~~~ <- エラーデス
みたいな
こちらの環境の問題かと思った
普段どうやって開発してるんでしょうか
Cloneした時点では、各改行文字はCRLFなのだろうか?LFなのだろうか?
おそらくCRLFなのだろう
eslintの警告が発生しているから
では、元のソースはCRLFなのだろうか?
それだと開発時に困るだろう
git clone時に改行コードが変更されている?
本当だった
GitHub上のリポジトリをクローンしてくると環境の問題が多い
基本的には、WSL上で開発するのが良さそう
気づいた点
chalkの4.1.2時点でのコードを見に行くと、CommonJS形式になっている 思い出すこと
esModuleInteropを指定するべきである
指定せずに、ここまでプロジェクトが続いているのはなぜだろうか?
デフォルトでESModuleInteropが有効になっている?
このパッケージのtsconfig.jsonは、いくつかの設定を継承している
このtsconfig.jsonで、esModuleInteropが指定されている
この設定が問題なく使われる環境であれば、esModuleInteropはtrueとなる
ここまで見て、tsconfig.jsonに追加していたesModuleInteropを削除したところ、エラーは発生しなかった
後味の悪い終わり方
hygenの場合、「DEBUG」環境変数を見ている シェル変数を渡せばよい
$ DEBUG=true pnpm hygen generator test
などとした
これはシェル変数だと思っていたが、環境変数のようだ
この記事が詳しいので、ここには書かない。
code:error.txt
Loaded templates: _templates
Error: Could not find matching close tag for "<%=".
details -----------
Error: Could not find matching close tag for "<%=".
at /home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:752:19
at Array.forEach (<anonymous>)
at Template.generateSource (/home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:742:15)
at Template.compile (/home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:587:12)
at Object.compile (/home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:398:16)
at handleCache (/home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:235:18)
at Object.exports.render (/home/user/hygen/node_modules/.pnpm/ejs@3.1.9/node_modules/ejs/lib/ejs.js:425:10)
at renderTemplate (/home/user/hygen/src/render.ts:29:34)
at /home/user/hygen/src/render.ts:80:17
at Array.map (<anonymous>)
-------------------
throwされたあとの経過を辿る
errorは、ejs.js内のforEach内でthrowされる
以降、このログに表示されている関数に、throwされたerrorをcatchするものがなかった
render関数を呼び出しているのは、engine
engine関数を呼び出しているrunnerで、ログを出力する記述を発見した
通常時に出力される、errorのtoString()は、ejsが吐き出すCould not ....のみ
パースを行うejsが、renderの使用者に Could not ...という文字列しか返さないことが分かった
hygenは、パースにどこで失敗したのかを知ることはできない。
ejsのejs.jsを読む必要が生じた
解決への道
新しいパース関数を書く?
おそらく従来のejsのパーサは、パース結果以外を返さない
構造化されたエラーやメタ情報を返せるメソッドを作れば解決
コストが大きい
Errorオブジェクトに、詳細なデータを吊り下げる
これが現実的?
この方針でIssueを送る
Errorメッセージを詳細にする
この問題に関しては、ejsにissueがあった
ejs:Issue「#119 Is it possible to get the line number in the ejs errors?」(2015/11/5)
ejs:PR「Fixed issue https://github.com/mde/ejs/issues/119」(2016/4/19)
Issue #119に付けられたコメント
ejs:PR「#202 Add EJS-Lint notice to syntax error message」(2016/9/14)
文法エラーがあったとき、EJS-Lintの使用を推奨するようになる
⇒ ejsファイル内の文法エラーは、ejs本体ではなくEJS-Lintで確認するのが(ejsのContributor的に)適切な対応。
ejs本体の文法エラーを指摘させるためにejs本体が肥大化させるような対応は許容されない
EJS-LintのREADME.mdによれば、ejsのライブラリ(本体)が小さくなるように努めているという Why can't EJS do this?
At EJS, we try to keep the library lightweight.