vscode-language-reviewを公開します

vscode-language-reviewは、VSCode (Visual Studio Code)でRe:VIEWマークアップドキュメントを編集しやすくするためのVSCode拡張です。

Visual Studio Marketplaceで公開しているので、VSCodeから簡単にインストールできます(作者がatsushienoのほうです)。

installing vscode-language-review

ソースコードgithub (atsushieno/vscode-language-review)で公開しています。

screenshot

Re:VIEWの文化的・技術的背景

Re:VIEWは、一部の技術系同人誌界隈ではよく使われているフォーマットで、Webページとしての表示に加えて、紙媒体を意識したレイアウトに適している記法を多くサポートしています。わたしがよく寄稿しているTechBoosterでは、このRe:VIEWを使用して同人誌を発行していますし、Re:VIEWを使いこなすためのガイドも公開しています

VSCodeでRe:VIEWをサポートするということは、具体的には次のような機能が期待されます。

  • (ライブ)プレビュー表示
  • タグジャンプ
  • 文法/表記チェック

Re:VIEWは、ツールとしては、テキスト、HTML、PDF等への変換処理を行うものであり、本家rubyで開発されているのですが、これをJavaScript環境向けに移植したreview.jsというものがあります。また、Atomプラグインlanguage-reviewも開発されています。

VSCodeはnodeアプリケーションであり、VSCode拡張を開発するには、JavaScriptライブラリを扱うのが最適です。

ゼロから始めるVSCode拡張の開発

vscodeは一般的なnodeアプリケーションであり、オープンソースで開発されています。一般的なnodeアプリケーションは、npmでビルドの実行、パッケージ作成、インストールができるようになっています。

vscodeの実体は、さまざまなモジュールの集合体です。Electronなどのサードパーティ部品と同様、vscode用に開発された独立モジュールも数多くnode_modulesとして参照しています。githubMicrosoftアカウントには、vscode用のモジュールが大量に含まれています

vscode拡張は、vsixというパッケージとして、Visual Studio MarketplaceのVisualStudioCodeカテゴリ以下で配布できます(VSCode本体からインストールできるようにする必要がなければ、単独でビルドしたものを配布しても良いでしょう)。vsixパッケージは、vsceというツールを使用してプロジェクトのディレクトリから直接生成してmarketplaceに送信できます。vscode拡張のnodeプロジェクト自体は、標準的なnodeパッケージとして開発・配布できます。

vscode拡張を作成する一番簡単な方法は、yeoman generator経由で利用できるvscode用テンプレートをスタート地点にすることです。vscode-generator-codeをインストールした後、 yo code を実行すると、vscode拡張用のテンプレートを作成するためのダイアログが表示されます。

yo code

11/06 追記: スクリーンショットが自前の修正版のものになってしまっていて、New Languageの選択肢が2つ出てしまっていますが、公式版のvscode-generator-codeにあるのは1つだけです。

今回のvscode-language-reviewの場合は、ここでNew Languageを選んで始めたわけですが、(2016年10月時点では)テンプレートにTypeScriptが存在しないため、JavaScriptベースのテンプレートが展開されました。その結果、.vscodeディレクトリの内容を含む基本的な構成がJavaScript用となってしまい、後になってハマることになりました(具体的には、プロジェクトのビルドが走らないとか、プロジェクトがデバッグできないとか)。New Languageテンプレートを選択しないと調整されない項目もあるので、この辺りは痛し痒しです。筆者はTypeScript用のテンプレートを含むforkを作成しているので、それを使う手もあります。

ともあれ、JavaScriptテンプレートを選択したけど、TypeScriptで開発したいという場合は(vscode拡張の場合よほどの事情がなければTypeScriptで良いのではないでしょうか)、TypeScriptテンプレートから生成される .vscode フォルダの内容を、自分のプロジェクトにコピーすると良いでしょう。

VSCode拡張の実行のブートストラップ

テンプレートNew Extension (TypeScript) からプロジェクトを作成すると、 src/extension.ts というファイルが作成されます。これがこの拡張のエントリポイントになります。

vscode拡張は、通常のnpmパッケージと同様、package.jsonにさまざまな情報を記述して、実行したり、パッケージしたりすることになります。package.jsonのトップレベル要素はobjectですが、この中に main というキーがあって、その値に実行するJavaScriptファイル名を指定することで、それがそのvscode拡張のエントリポイントを探すファイルになります。TypeScriptの場合は、上記テンプレートから作成すると ./out/src/extension となっています。VSCodeは、このスクリプトの中から、activate() という関数を探して呼び出します。

export function activate (context : vscode.ExtensionContext) { ... }

この関数の中で、自分のvscode拡張の初期化処理を行うことになります。vscode-language-reviewの場合は、ここでpreview機能をVSCodeのコマンドとして登録しています。

package.jsonの内容や、vscode拡張の基本的なファイル構成については、vscodeサイトの説明がとてもわかり易く書かれているので、これを参考にすると良いでしょう。

TypeScriptプロジェクトにした場合は、 package.json と並んで tsconfig.json というファイルがあります。これは、TypeScriptコンパイラでこのプロジェクトをビルドする際に使用されるオプションを記述しておくためのファイルです。基本的に、TypeScriptプロジェクトのテンプレートから変更する必要は無いでしょう。ここに、例えば "sourceMap": true という記述がないと、tsソースファイルから、実行するjsファイルを出力した際に、デバッグ実行に必要なsourcemapが生成されなくなってしまいます。

もうひとつ、vscodeでは、拡張プロジェクトのフォルダを開いている時に、F5キーを押すだけでデバッグ実行を開始できますが、その際には .vscode という隠しフォルダ(Unix系OSの場合)の中にある各種ファイルの内容が重要になります。これも基本的にテンプレートから生成される内容を修正する必要はないでしょうが、これがVSCodeの想定外の内容になっていると、正常なデバッグ実行が行えなくなる可能性があります(筆者はJSテンプレートからTSプロジェクトを作成していたため、ここでハマりました)。また、.vscodeの内容は個人設定のような性質のものではないので、リポジトリにcheckinしておく必要があります(そうしないと、他の人がビルドできません)。

vscode-language-reviewモジュール

vscodeの言語サポートパッケージは、Microsoftとしては vscode-language-XXX という名前を慣習的に使用しているようです(例: Microsoft/vscode-language-json, Microsoft/vscode-language-css)。今回のreviewサポート拡張もこの命名規則に倣っています。

vscode-language-reviewのpreview機能でやっていることは、markdownのpreviewに近いです。その具体的な実装は、簡潔に言えば、以下の2ステップで実現しています。

  • アクティブドキュメントの内容をre:viewドキュメントとしてreview.jsのAPIで変換する。review.start()で変換処理を行いますが、その際にその引数パラメーターControllerを設定することで、具体的な変換処理を指示します。基本的にはreview.js本体に含まれているサンプルをもとに作成しています。
  • vscode.previewHtmlというカスタムコマンドを使用して表示する。カスタムコマンドとは、vscodeの高水準APIとして組み込まれている機能で、vscode拡張を書いている時は、コマンドAPI vscode.commands.executeCommand() を使って呼び出せます。

review.jsのstart()関数から変換した結果生成されたHTMLは、あくまでbody要素の内容のみ、という感じで、その内容をそのまま先の vscode.previewHtml で表示させると、画像が全く展開されませんでした。これは、HTMLに(headの内容となるべき)base要素などが存在せず、結果的に画像の相対パスが解決できなかったことが原因だったので、base要素はreview.jsの変換結果に継ぎ足すようにしました。

ここまで出来て、とりあえず原稿のライブプレビューは出来たようだと判断したので、vscode-language-review 0.1.0として公開しました。今後もセクションジャンプやprhによる校正支援などを取り込みたいなあと思っています(が、もし誰か他にやってくれる人がいたら大変嬉しいです…!)

とりあえず、最低限の機能はできていると思うので、VSCodeでRe:VIEW原稿を編集したいという方はぜひ使ってみてください。

感謝

この拡張を作るにあたっては、vscode拡張の先駆けとして vscode-uiflowのソースがとても参考になりました。