Chrome(Canary) の Native File System API で ローカルファイルの読み書きをする
ブラウザ上でローカルファイルの読み書きができる Native File System API が ChromeCanary で実装された。
前々から欲しかった機能なので、自分が作ってる markdown preview ツールに実装してみた。
- Intent to ship https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/noan0cgEBGQ/t8DuK8_hDwAJ
- 仕様 http://wicg.github.io/native-file-system/
動かすとこんな感じ
https://mdbuf.netlify.com/ で Meta+O/Meta+S のキーバインドを振ってる。
有効化
- https://www.google.com/intl/ja/chrome/canary/ をダウンロード
- chrome://flags/#native-file-system-api を開いて Enabled
- リロードして https://mdbuf.netlify.com/ を開く
できること
- Cmd+O でファイルを開く
- Cmd+S で保存できる
- 一度保存したら Cmd+S で保存し続けられる
- Cmd+Shift+S で別名で保存
よくあるデスクトップアプリに寄せてる。GUI メニューは作ってない(いるか?)
できないこと
- Read & Write な API がないので、読みこんだコンテキストで書き込む、みたいなものができない
- リロード時にパーミッションを持ち越せないので、開き直したら Cmd+S で再度パーミッションを取得し直す必要がある
- セキュリティ上の理由でフルパスが取れない
簡単なコードの例
const tx = document.createElement("textarea") as HTMLTextAreaElement; async function writeFile(handler: any, text: string): Promise<void> { const writer = await handler.createWriter(); await writer.truncate(0); await writer.write(0, text); await writer.close(); } // mount open button const btn = document.createElement("button"); btn.textContent = "Open file and edit!"; document.body.appendChild(btn); btn.addEventListener("click", async (ev: any) => { let handler: any = null; try { handler = await window.chooseFileSystemEntries({ type: "saveFile", accepts: [ { description: "Text file", extensions: ["txt"], mimeTypes: ["text/plain"] } ] }); } catch (err) { alert("Please select file"); return; } tx.style = "width: 80vw; height: 80vh"; document.body.appendChild(tx); tx.addEventListener("change", async (ev: any) => { await writeFile(handler, ev.target.value); }); btn.remove(); });
window.chooseFileSystemEntries(...)
を呼ぶとモーダルが出る。これはクリックのようなユーザーのアクション起点でないと起動できない。(フルスクリーンAPIなどと同じ)
感想
在りし日の ActiveX を彷彿とさせる…(さすがにあれほど自由なパーミッションではないが)
単機能なエディタにはいいけど、複数ファイルを読み書きするにはまだ貧弱。まずは単機能なエディタを作っていくと良さそう。たとえば React のプレビューツールとか。
ディレクトリのパーミッションが取れる機能があって、その場合ファイルブラウザが作れる?んだろうか。あとで試す。
ただ、最近の safari はこういう PWA 系の機能を最近実装しないのが気がかりで、 しばらくは PC/Android Chrome で動くものと割り切ったほうがいいような気もしてる。