Neovimで編集中のMDN Web Docsのプレビューを開くコマンドを書いた

NeovimでMDN Web Docsの翻訳にコントリビュートするなら便利なコマンド作ってみました。
2022.12.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも。CX事業本部Delivery部のえーたん(@eetann092)です。

筆者は今まで3回MDN Web Docsに翻訳コントリビュートしました。作業中、Neovimからすぐにプレビューを開きたかったため、コマンドを書いてみました。

以下が書いたコマンドを使った例です。

大まかな流れ

処理の大まかな流れは以下です。なお、contentリポジトリのディレクトリでyarn startを実行中であることが前提です。

  1. 言語を取得する(例:ja
  2. スラッグを取得する(例:Mozilla/Add-ons/WebExtensions/API
  3. 取得した言語とスラッグをもとに、URLを作成する
  4. URLをブラウザで開く

指定したURLをブラウザで開く部分は、open-browser.vimを使います。

今回は、以下のようにopen_preview_mdn_web_docsという関数で実装しました。

local function open_preview_mdn_web_docs(select_language)
  -- 後で説明
end

vim.api.nvim_create_user_command("OpenPreviewMdn", function()
	open_preview_mdn_web_docs()
end, {})

vim.api.nvim_create_user_command("OpenPreviewMdnSelect", function()
	open_preview_mdn_web_docs(true)
end, {})

筆者は開いているファイルが日本語版だったとしても、英語版も確認したいことがありました。そのため、引数で言語選択のあり/無しを指定できるようにし、コマンドも分けています。

言語選択を手動で行う例が以下です。

上記ではnoice.nvimを導入している状態ですので、noice.nvimが入っていない動作例もお見せします。

関数の中身

全体やシンタックスハイライト付きで見たい方は筆者のdotfilesをどうぞ。

ここからは関数の中身を区切って説明していきます。

Markdown判定

まず、Markdown以外ではMarkdown Onlyと表示して終了させます。

local port = 5042
local language = nil
local fullPath = vim.fn.expand("%:p")

if vim.bo.filetype ~= "markdown" then
  print("Markdown Only")
  do
    return
  end
end

言語の選択

次に、言語の選択です。引数で指定した言語選択のあり/無しを使って分岐します。

if select_language then
  -- 手動で言語を選択
  -- ...後で説明
else
  -- パスから言語を取得
  language = string.match(fullPath, ".*files/(.-)/")
  if language == nil then
    language = "en-US"
  end
end

elseの部分が言語を自動で選択する場合です。言語をパスから取得しています。

言語の手動選択にはvim.ui.selectを使ってみました。キャンセルした場合は終了します。

-- 手動で言語を選択
vim.ui.select({ "English", "Japanese", "French" }, {
  prompt = "Select language:",
}, function(choice)
  if choice == "English" then
    language = "en-US"
  elseif choice == "Japanese" then
    language = "ja"
  elseif choice == "French" then
    language = "fr"
  end
end)
-- 選択をキャンセルした場合は終了
if language == nil then
  print("See you")
  do
    return
  end
end

slugの取得

slugはMarkdownファイルのフロントマターから取得します。10行以内に無かったら諦める仕様です。

local slug = ""
local file = io.open(fullPath, "r")
if file == nil then
  do
    return
  end
end
local count = 1
for line in file:lines() do
  local cap = string.match(line, "slug: (.*)")
  if cap ~= nil then
    slug = cap
    break
  end
  count = count + 1
  if 10 < count then
    break
  end
end
file:close()

最後に、URLを生成してopen-browser.vimを使って開きます。

local url = string.format("http://localhost:%d/%s/docs/%s", port, language, slug)
vim.cmd(string.format("OpenBrowser %s", url))

最後に

今回はcontentリポジトリでyarn startを実行していることが前提でまだ完全に自動ではありませんが、以前よりも作業が楽になりました。ブラッシュアップしたら随時更新します。

全体やシンタックスハイライト付きで見たい方は筆者のdotfilesをどうぞ。