Monacoエディタで内容が変更されたかどうか調べる

2024-01-15

結論:getAlternativeVersionId()で判定できる。

あらまし

ブラウザ上で動くテキストエディタとしてMonacoエディタを使った際に、ページを閉じたりリロードされた場合に内容が失われないようにするため、内容が変更されているかどうかを知りたかった。 しかしググってもなかなかそれらしい情報を得られなかった。 元の内容のコピーを保持しておいて現在の内容と比較すれば判定はできるけどテキストが巨大な場合は無駄だし、アンドゥした場合と書き換えて戻した場合の判別がつかない。

「変更検知はeditor.onDidChangeModelContentを使えばよい」と出てくるが、 そのコールバックに渡されるイベント情報のversionIdはアンドゥでも常にインクリメントされてしまうため、判定できない。

どうしたものかと結構詰まってたんだけど、APIのリファレンスを見ていてようやく見つけた。

コード例

const editor = monaco.editor.create(document.getElementById('editor'), {...})
editor.setValue('テキストの内容')

let savedVersionId = editor.getModel().getAlternativeVersionId()

window.addEventListener('beforeunload', event => {
if (savedVersionId !== editor.getModel().getAlternativeVersionId()) {
// テキストに変更あり:保存するかどうかのダイアログを出すなど
event.preventDefault()
event.returnValue = ''
}
})
// editor.onDidChangeModelContentのコールバック内で判定して画面表示に反映、とかも可