Electronで「要素の検証」を再現する方法


本文

初投稿です。
Chromeで右クリックすると出てくる「検証(I)」。
押すとデベロッパーツール内でカーソル直下の要素にジャンプします。
Electron内でも使えると開発中なにかと便利なので、この機能を再現してみます。

openDevTools

Electronで単にデベロッパーツールを開く場合はwebContents.openDevTools([options])を使います。

const { remote } = require('electron')
const webContents = remote.getCurrentWindow()
webContents.openDevTools()

modeオプションで表示位置の指定ができます。

mode 状態
right 画面右に表示
bottom 画面下に表示
detach 別ウィンドウに切り離して表示
undocked 別ウィンドウに切り離すが画面内に戻すこともできる
webContents.openDevTools({ mode: 'undocked' })

※webviewタグによって作られたwebContentsにはmodeの指定ができないようです。(detachのみ)
https://electronjs.org/docs/api/web-contents#contentsopendevtoolsoptions

inspectElement

一方、webContents.inspectElement(x, y)は指定された位置の要素をデベロッパーツール内で開きます。

以下はマウス右クリックで「要素の検証」メニューを表示するサンプルです。
右クリックを使うアプリだと、イベントが干渉してしまうので僕は中央ボタンに割り当てています。

  const { remote } = require('electron')
  const { Menu, MenuItem } = remote
  const webContents = remote.getCurrentWindow()

  // 2 にするとマウス中央ボタンでメニュー表示
  const triggerButton = 3

  let clickPosition = null

  const contextMenu = new Menu()

  const inspectElement = new MenuItem({
    label: '要素の検証',
    click () {
      webContents.inspectElement(...clickPosition)
    }
  })

  contextMenu.append(inspectElement)

  const onclick = ({ x, y, which }) => {
    if (which === triggerButton) {
      event.preventDefault()
      clickPosition = [x, y]
      contextMenu.popup(webContents)
    }
  }

  window.addEventListener('auxclick', onclick)

webpackを使っている場合は以下のif文で囲み、プロダクションビルドで除外することをおすすめします。

if (process.env.NODE_ENV !== 'production') {
...
}

参考

https://electronjs.org/docs/api/web-contents
https://stackoverflow.com/questions/32636750