私はFirefox向けにTab Session Managerという拡張機能を作っています。これは開いているセッションを保存・復元するアドオンで,機能の一つとして保存されたセッションをファイルに書き出してバックアップを保存するオプションがあります。以前は保存場所を特定のフォルダに固定していたのですが,この度保存フォルダを文字列で指定できるオプションを実装することにしました1。
前提
ユーザは拡張機能の設定ページからこのようなフォームに入力します。
ここに入力されたフォルダ名を指定してファイルの保存処理を行うわけですが,例えばfolder?
と入力されると保存処理はエラーを吐きます。?
はファイル名として使用できないためです。したがって,?
を-
に変換するなどしてエラーを回避する必要があります。
やること
- 今回は上記の画像の通りフォルダ名のみを対象とする
- フォルダ名に含まれる特殊文字はハイフンに変換する
-
a:b?c.d"e<f>g|h
→a-b-c-d-e-f-g-h
- 今回はフォルダ名が対象なので,ピリオドも特殊文字として扱う
- ディレクトリの区切り文字として使えるのはスラッシュまたはバックスラッシュとし,出力はバックスラッシュに統一する
-
a/b\c
→a\b\c
- 2つ以上連続するスペース,バックスラッシュは1つに変換する
-
a___a\\b
→a_a\b
(スペースを_
で表しています) - フォルダ名の先頭と末尾のスペースは削除する
-
a_\_b_
→a\b
(スペースを_
で表しています) - パスの先頭と末尾のバックスラッシュは削除する
-
\a\
→a
- OSによって予約された名前(CON,PRNなど)やパスの最大長は今回は考えない
実装
const replaceFolderName = str => {
const specialChars = /\:|\?|\.|"|<|>|\|/g; //使用できない特殊文字
const slash = /\//g; //単一のスラッシュ
const spaces = /\s\s+/g; //連続したスペース
const backSlashs = /\\\\+/g; //連続したバックスラッシュ
const sandwich = /(\s\\|\\\s)+(\s|\\)?/g;//バックスラッシュとスペースが交互に出てくるパターン
const beginningEnd = /^(\s|\\)+|(\s|\\)+$/g; //先頭と末尾のスペース,バックスラッシュ
const replacedStr = str
.replace(specialChars, `-` ) //特殊文字をハイフンに置き換え
.replace(slash, `\\`) //スラッシュをバックスラッシュに置き換え
.replace(spaces, ` ` ) //連続するスペースを一つに置き換え
.replace(backSlashs, `\\`) //連続するバックスラッシュを一つに置き換え
.replace(sandwich, `\\`) //" \ \"のような"サンドイッチ"をバックスラッシュ一つに置き換え
//→フォルダ名の先頭と末尾のスペースを削除,スペースのみのフォルダを削除
.replace(beginningEnd, `` ); //先頭と末尾のスペース,バックスラッシュを削除
return replacedStr;
};
サンプルはこちら
こんな感じにすれば不正なフォルダ名のエラーを回避できる……はずです。
見落としている点やもっとエレガントな方法があれば教えて頂けると幸いです。
-
フォルダをinput type=fileではなく入力文字列で指定するのは,拡張機能から指定できる保存先がFirefoxのダウンロードフォルダ以下に限定されるためです。ダウンロードフォルダ以外を指定できないUIにしたいという意図があります。
フォルダ名をユーザに入力させる上で考えなければいけないことは,フォルダ名には使用できない文字列があるということです。この記事では,フォルダ名として不正な文字列が入力されたときにいい感じに変換する方法を説明します。 ↩