Corredor

ウェブ、プログラミングの勉強メモ。

指定ディレクトリ配下の Markdown ファイルに含まれる NFD・NFC 文字を一括相互変換する

Windows ユーザと Mac ユーザが入り混じって、Markdown ファイルを書いていた時に起こった、俗に NFD 問題と言われるアレ。


Mac の Finder で表示されるディレクトリ名やファイル名は、「NFD」という形式で Unicode 正規化されている。平たくいうと、「ガ」とか「プ」とかのように濁点・半濁点が付いた文字列を、「カ」「゛」、「フ」「゜」と2文字に分割して表現する、という仕様。見た目には違いがほぼ分からないのだが、Mac の Finder からファイル名をコピペすると、このように NFD 正規化された文字列が取得できてしまう。

対して、Windows のエクスプローラで見えるフォルダ名やファイル名は、「NFC」という形式で Unicode 正規化されている。コチラは通常どおり、「ガ」で1文字、「プ」で1文字とする仕様だ。

複数の Markdown ファイルを書いていて、Markdown ファイル同士のリンクを書いていたのだが、Mac ユーザは Finder から、Windows ユーザはエクスプローラから、リンク先のファイル名をコピペして Markdown リンクを書いていたため、リンクパスに NFD 正規化された文字列と NFC 正規化された文字列とが混在してしまうことになった。こうなると、Mac 環境では Windows ユーザが書いた Markdown リンクが効かないし、Windows ユーザは Mac 環境で書いたリンクが効かない。

コレは不便だということで、指定のディレクトリ配下にある Markdown ファイルを全て拾い上げて、その中に NFD 文字が出てきたら NFC 文字に変換する Node.js スクリプトと、その逆に NFC 文字を NFD 文字に変換する Node.js スクリプトの2つを作った。

ソースコードは以下の Gist に上げた。

4つファイルがあるが、以下のように2ファイルずつ使う。

  • nfd-to-nfc.jsnfd-to-nfc-func.js : NFD 文字を NFC 文字に変換する
    • Mac ユーザが書いた Markdown リンクを、Windows 環境で動作するように修正する、Windows ユーザ向けのスクリプト
  • nfc-to-nfd.jsnfc-to-nfd-func.js : NFC 文字を NFD 文字に変換する
    • Windows ユーザが書いた Markdown リンクを、Mac 環境で動作するように修正する、Mac ユーザ向けのスクリプト

このスクリプトを使うには、replaceunorm という2つの npm パッケージが必要なので、以下のようにインストールしておく。

$ npm install --save-dev replace unorm

複数ファイルを対象に一括置換する操作は replace ライブラリに任せている。replace ライブラリで置換処理を細かく実装する都合上、*-func.js という別ファイルを作っている。

unorm パッケージは、NFD 濁点、NFD 半濁点を取得するために使用している。NFD 正規化した時に使われる濁点・半濁点は「結合文字」と呼ばれる、特殊な文字コードのモノになる。

拙作の Angular Utilities に「Normalize To NFC」というツールを作ってあるが、NFD 濁点は ゙、NFD 半濁点は ゙ という文字コードになる。通常「だくてん」「はんだくてん」と変換して出てくる、全角の濁点文字は ゚、半濁点文字は ゜ となっている。この他に半角の濁点、半濁点も別の文字コードで定義されていたりする。

ひとまずこんなスクリプトを書いて、NFD・NFC が混在する状態は解消できた。一般的には、Mac Finder で用いられる「NFD」の仕様の方が嫌われるので (「ガ」が「カ゛」と記述されると「ガ」で検索してもヒットしない)、NFC 形式に合わせておくのが良いだろう。

ちなみに、Markdown でテキストを書いている時に NFD 文字が含まれているかチェックするには、textlint-rule-no-nfd が簡単。

以上。ハ゛イハ゛イ。

Web制作者のためのGitHubの教科書 チームの効率を最大化する共同開発ツール Web制作者のための教科書シリーズ

Web制作者のためのGitHubの教科書 チームの効率を最大化する共同開発ツール Web制作者のための教科書シリーズ