LoginSignup
5
4

More than 1 year has passed since last update.

Native File System API でテキストエディタを作る

Last updated at Posted at 2021-10-22

先日公開された vscode.dev を触った際、なんか Native File System API というのを使えばブラウザから普通にローカルファイルを扱えると知ったので、試しにブラウザで動くテキストエディタを作ってみた。

Chromium 系のブラウザ (Chrome, Edge など) だと大体動くけど Brave はだめ らしい。http サーバーを立てずに、ローカルの HTML ファイルとして開いても動く。

注意点としては、既存ファイルを上書き保存をすると作成日が保存した時点になってしまう。

_SS 2021-10-22 15.03.08.png

html
<div id='filename'>名称未設定ファイル</div>
<textarea id='editor'></textarea>
<div>
    <button id='open'>開く</button>
    <button id='save'>上書き保存</button>
    <button id='saveas'>名前をつけて保存</button>
</div>
css
#editor {
    width: 320px;
    height: 160px;
}
#filename {
    color: #888888;
}
JS
const fileNameDiv = document.getElementById('filename')
let fileHandle

// テキストファイルだけ開けるようなオプション
const pickerOpts = {
    types: [
        {
            description: 'Texts',
            accept: {
                'text/*': ['.txt', '.text']
            }
        }
    ],
    multiple: false,
}

document.getElementById('open').onclick = async () => {
    try {
        [ fileHandle ] = await window.showOpenFilePicker(pickerOpts)
        if (fileHandle.kind !== 'file') return

        fileNameDiv.textContent = fileHandle.name
        const fileData = await fileHandle.getFile()
        const content = await fileData.text()
        document.getElementById('editor').value = content
    } catch (e) {
        // ファイル選択をキャンセルした時などにここに飛ぶ
        console.error(e)
    }

}

document.getElementById('save').onclick = async () => {
    if (fileHandle.kind !== 'file') return

    const content = document.getElementById('editor').value
    const writableStream = await fileHandle.createWritable()
    await writableStream.write(content)
    await writableStream.close()
}

document.getElementById('saveas').onclick = async () => {
    try {
        const content = document.getElementById('editor').value
        fileHandle = await window.showSaveFilePicker(pickerOpts)
        if (fileHandle.kind !== 'file') return

        const writableStream = await fileHandle.createWritable()
        await writableStream.write(content)
        await writableStream.close()

        fileNameDiv.textContent = fileHandle.name

    } catch (e) {
        console.error(e)
    }
}
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4