chore: type check JS in docs (#38423)
* build(deps): update @electron/lint-roller * chore: type check JS in docs * docs: add @ts-check and @ts-expect-error to code blocks * chore: fix type check errors in docs * chore: add ts-type to blocks
This commit is contained in:
parent
4c89061e0e
commit
905aad9cb6
49 changed files with 257 additions and 182 deletions
|
@ -971,7 +971,7 @@ app.setJumpList([
|
||||||
title: 'Tool A',
|
title: 'Tool A',
|
||||||
program: process.execPath,
|
program: process.execPath,
|
||||||
args: '--run-tool-a',
|
args: '--run-tool-a',
|
||||||
icon: process.execPath,
|
iconPath: process.execPath,
|
||||||
iconIndex: 0,
|
iconIndex: 0,
|
||||||
description: 'Runs Tool A'
|
description: 'Runs Tool A'
|
||||||
},
|
},
|
||||||
|
@ -980,7 +980,7 @@ app.setJumpList([
|
||||||
title: 'Tool B',
|
title: 'Tool B',
|
||||||
program: process.execPath,
|
program: process.execPath,
|
||||||
args: '--run-tool-b',
|
args: '--run-tool-b',
|
||||||
icon: process.execPath,
|
iconPath: process.execPath,
|
||||||
iconIndex: 0,
|
iconIndex: 0,
|
||||||
description: 'Runs Tool B'
|
description: 'Runs Tool B'
|
||||||
}
|
}
|
||||||
|
@ -1418,8 +1418,8 @@ const fs = require('fs')
|
||||||
let filepath
|
let filepath
|
||||||
let bookmark
|
let bookmark
|
||||||
|
|
||||||
dialog.showOpenDialog(null, { securityScopedBookmarks: true }, (filepaths, bookmarks) => {
|
dialog.showOpenDialog(null, { securityScopedBookmarks: true }).then(({ filePaths, bookmarks }) => {
|
||||||
filepath = filepaths[0]
|
filepath = filePaths[0]
|
||||||
bookmark = bookmarks[0]
|
bookmark = bookmarks[0]
|
||||||
fs.readFileSync(filepath)
|
fs.readFileSync(filepath)
|
||||||
})
|
})
|
||||||
|
|
|
@ -104,6 +104,7 @@ window, you have to set both `parent` and `modal` options:
|
||||||
```javascript
|
```javascript
|
||||||
const { BrowserWindow } = require('electron')
|
const { BrowserWindow } = require('electron')
|
||||||
|
|
||||||
|
const top = new BrowserWindow()
|
||||||
const child = new BrowserWindow({ parent: top, modal: true, show: false })
|
const child = new BrowserWindow({ parent: top, modal: true, show: false })
|
||||||
child.loadURL('https://github.com')
|
child.loadURL('https://github.com')
|
||||||
child.once('ready-to-show', () => {
|
child.once('ready-to-show', () => {
|
||||||
|
@ -597,7 +598,7 @@ On Linux the setter is a no-op, although the getter returns `true`.
|
||||||
|
|
||||||
A `boolean` property that determines whether the window is excluded from the application’s Windows menu. `false` by default.
|
A `boolean` property that determines whether the window is excluded from the application’s Windows menu. `false` by default.
|
||||||
|
|
||||||
```js
|
```js @ts-expect-error=[11]
|
||||||
const win = new BrowserWindow({ height: 600, width: 600 })
|
const win = new BrowserWindow({ height: 600, width: 600 })
|
||||||
|
|
||||||
const template = [
|
const template = [
|
||||||
|
@ -1200,6 +1201,9 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
|
||||||
method:
|
method:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
const { BrowserWindow } = require('electron')
|
||||||
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
const url = require('url').format({
|
const url = require('url').format({
|
||||||
protocol: 'file',
|
protocol: 'file',
|
||||||
slashes: true,
|
slashes: true,
|
||||||
|
@ -1213,6 +1217,9 @@ You can load a URL using a `POST` request with URL-encoded data by doing
|
||||||
the following:
|
the following:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
const { BrowserWindow } = require('electron')
|
||||||
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
win.loadURL('http://localhost:8000/post', {
|
win.loadURL('http://localhost:8000/post', {
|
||||||
postData: [{
|
postData: [{
|
||||||
type: 'rawData',
|
type: 'rawData',
|
||||||
|
|
|
@ -104,7 +104,7 @@ The `callback` function is expected to be called back with user credentials:
|
||||||
* `username` string
|
* `username` string
|
||||||
* `password` string
|
* `password` string
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={request:Electron.ClientRequest}
|
||||||
request.on('login', (authInfo, callback) => {
|
request.on('login', (authInfo, callback) => {
|
||||||
callback('username', 'password')
|
callback('username', 'password')
|
||||||
})
|
})
|
||||||
|
@ -113,7 +113,7 @@ request.on('login', (authInfo, callback) => {
|
||||||
Providing empty credentials will cancel the request and report an authentication
|
Providing empty credentials will cancel the request and report an authentication
|
||||||
error on the response object:
|
error on the response object:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={request:Electron.ClientRequest}
|
||||||
request.on('response', (response) => {
|
request.on('response', (response) => {
|
||||||
console.log(`STATUS: ${response.statusCode}`)
|
console.log(`STATUS: ${response.statusCode}`)
|
||||||
response.on('error', (error) => {
|
response.on('error', (error) => {
|
||||||
|
|
|
@ -148,10 +148,7 @@ clipboard.
|
||||||
```js
|
```js
|
||||||
const { clipboard } = require('electron')
|
const { clipboard } = require('electron')
|
||||||
|
|
||||||
clipboard.writeBookmark({
|
clipboard.writeBookmark('Electron Homepage', 'https://electronjs.org')
|
||||||
text: 'https://electronjs.org',
|
|
||||||
bookmark: 'Electron Homepage'
|
|
||||||
})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### `clipboard.readFindText()` _macOS_
|
### `clipboard.readFindText()` _macOS_
|
||||||
|
|
|
@ -18,7 +18,7 @@ contextBridge.exposeInMainWorld(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
// Renderer (Main World)
|
// Renderer (Main World)
|
||||||
|
|
||||||
window.electron.doThing()
|
window.electron.doThing()
|
||||||
|
@ -104,7 +104,7 @@ contextBridge.exposeInIsolatedWorld(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
// Renderer (In isolated world id1004)
|
// Renderer (In isolated world id1004)
|
||||||
|
|
||||||
window.electron.doThing()
|
window.electron.doThing()
|
||||||
|
|
|
@ -10,7 +10,9 @@ title is `Electron`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// In the main process.
|
// In the main process.
|
||||||
const { desktopCapturer } = require('electron')
|
const { BrowserWindow, desktopCapturer } = require('electron')
|
||||||
|
|
||||||
|
const mainWindow = new BrowserWindow()
|
||||||
|
|
||||||
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
|
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
|
||||||
for (const source of sources) {
|
for (const source of sources) {
|
||||||
|
@ -22,7 +24,7 @@ desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources =
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
// In the preload script.
|
// In the preload script.
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ and a directory selector, so if you set `properties` to
|
||||||
`['openFile', 'openDirectory']` on these platforms, a directory selector will be
|
`['openFile', 'openDirectory']` on these platforms, a directory selector will be
|
||||||
shown.
|
shown.
|
||||||
|
|
||||||
```js
|
```js @ts-type={mainWindow:Electron.BrowserWindow}
|
||||||
dialog.showOpenDialogSync(mainWindow, {
|
dialog.showOpenDialogSync(mainWindow, {
|
||||||
properties: ['openFile', 'openDirectory']
|
properties: ['openFile', 'openDirectory']
|
||||||
})
|
})
|
||||||
|
@ -139,7 +139,7 @@ and a directory selector, so if you set `properties` to
|
||||||
`['openFile', 'openDirectory']` on these platforms, a directory selector will be
|
`['openFile', 'openDirectory']` on these platforms, a directory selector will be
|
||||||
shown.
|
shown.
|
||||||
|
|
||||||
```js
|
```js @ts-type={mainWindow:Electron.BrowserWindow}
|
||||||
dialog.showOpenDialog(mainWindow, {
|
dialog.showOpenDialog(mainWindow, {
|
||||||
properties: ['openFile', 'openDirectory']
|
properties: ['openFile', 'openDirectory']
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
|
|
|
@ -89,7 +89,7 @@ tuples. So, the even-numbered offsets are key values, and the odd-numbered
|
||||||
offsets are the associated values. Header names are not lowercased, and
|
offsets are the associated values. Header names are not lowercased, and
|
||||||
duplicates are not merged.
|
duplicates are not merged.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={response:Electron.IncomingMessage}
|
||||||
// Prints something like:
|
// Prints something like:
|
||||||
//
|
//
|
||||||
// [ 'user-agent',
|
// [ 'user-agent',
|
||||||
|
@ -100,5 +100,5 @@ duplicates are not merged.
|
||||||
// '127.0.0.1:8000',
|
// '127.0.0.1:8000',
|
||||||
// 'ACCEPT',
|
// 'ACCEPT',
|
||||||
// '*/*' ]
|
// '*/*' ]
|
||||||
console.log(request.rawHeaders)
|
console.log(response.rawHeaders)
|
||||||
```
|
```
|
||||||
|
|
|
@ -83,14 +83,14 @@ If `listener` returns a Promise, the eventual result of the promise will be
|
||||||
returned as a reply to the remote caller. Otherwise, the return value of the
|
returned as a reply to the remote caller. Otherwise, the return value of the
|
||||||
listener will be used as the value of the reply.
|
listener will be used as the value of the reply.
|
||||||
|
|
||||||
```js title='Main Process'
|
```js title='Main Process' @ts-type={somePromise:(...args:unknown[])=>Promise<unknown>}
|
||||||
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
|
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
|
||||||
const result = await somePromise(...args)
|
const result = await somePromise(...args)
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
```js title='Renderer Process'
|
```js title='Renderer Process' @ts-type={arg1:unknown} @ts-type={arg2:unknown}
|
||||||
async () => {
|
async () => {
|
||||||
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
|
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -101,7 +101,7 @@ The main process should listen for `channel` with
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={someArgument:unknown} @ts-type={doSomeWork:(arg:unknown)=>Promise<unknown>}
|
||||||
// Renderer process
|
// Renderer process
|
||||||
ipcRenderer.invoke('some-name', someArgument).then((result) => {
|
ipcRenderer.invoke('some-name', someArgument).then((result) => {
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -147,7 +147,7 @@ can have a submenu.
|
||||||
|
|
||||||
An example of creating the application menu with the simple template API:
|
An example of creating the application menu with the simple template API:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[107]
|
||||||
const { app, Menu } = require('electron')
|
const { app, Menu } = require('electron')
|
||||||
|
|
||||||
const isMac = process.platform === 'darwin'
|
const isMac = process.platform === 'darwin'
|
||||||
|
@ -267,7 +267,7 @@ menu on behalf of the renderer.
|
||||||
|
|
||||||
Below is an example of showing a menu when the user right clicks the page:
|
Below is an example of showing a menu when the user right clicks the page:
|
||||||
|
|
||||||
```js
|
```js @ts-expect-error=[21]
|
||||||
// renderer
|
// renderer
|
||||||
window.addEventListener('contextmenu', (e) => {
|
window.addEventListener('contextmenu', (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -289,7 +289,7 @@ ipcMain.on('show-context-menu', (event) => {
|
||||||
{ label: 'Menu Item 2', type: 'checkbox', checked: true }
|
{ label: 'Menu Item 2', type: 'checkbox', checked: true }
|
||||||
]
|
]
|
||||||
const menu = Menu.buildFromTemplate(template)
|
const menu = Menu.buildFromTemplate(template)
|
||||||
menu.popup(BrowserWindow.fromWebContents(event.sender))
|
menu.popup({ window: BrowserWindow.fromWebContents(event.sender) })
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ Example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Main process
|
// Main process
|
||||||
const { MessageChannelMain } = require('electron')
|
const { BrowserWindow, MessageChannelMain } = require('electron')
|
||||||
|
const w = new BrowserWindow()
|
||||||
const { port1, port2 } = new MessageChannelMain()
|
const { port1, port2 } = new MessageChannelMain()
|
||||||
w.webContents.postMessage('port', null, [port2])
|
w.webContents.postMessage('port', null, [port2])
|
||||||
port1.postMessage({ some: 'message' })
|
port1.postMessage({ some: 'message' })
|
||||||
|
@ -26,9 +27,9 @@ port1.postMessage({ some: 'message' })
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
ipcRenderer.on('port', (e) => {
|
ipcRenderer.on('port', (e) => {
|
||||||
// e.ports is a list of ports sent along with this message
|
// e.ports is a list of ports sent along with this message
|
||||||
e.ports[0].on('message', (messageEvent) => {
|
e.ports[0].onmessage = (messageEvent) => {
|
||||||
console.log(messageEvent.data)
|
console.log(messageEvent.data)
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
Process: [Main](../glossary.md#main-process)
|
Process: [Main](../glossary.md#main-process)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { netLog } = require('electron')
|
const { app, netLog } = require('electron')
|
||||||
|
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
await netLog.startLogging('/path/to/net-log')
|
await netLog.startLogging('/path/to/net-log')
|
||||||
|
|
|
@ -32,7 +32,7 @@ To have your custom protocol work in combination with a custom session, you need
|
||||||
to register it to that session explicitly.
|
to register it to that session explicitly.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { session, app, protocol } = require('electron')
|
const { app, BrowserWindow, net, protocol, session } = require('electron')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ app.whenReady().then(() => {
|
||||||
const ses = session.fromPartition(partition)
|
const ses = session.fromPartition(partition)
|
||||||
|
|
||||||
ses.protocol.handle('atom', (request) => {
|
ses.protocol.handle('atom', (request) => {
|
||||||
const path = request.url.slice('atom://'.length)
|
const filePath = request.url.slice('atom://'.length)
|
||||||
return net.fetch(url.pathToFileURL(path.join(__dirname, path)))
|
return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString())
|
||||||
})
|
})
|
||||||
|
|
||||||
mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
const mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -121,9 +121,9 @@ Either a `Response` or a `Promise<Response>` can be returned.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { app, protocol } from 'electron'
|
const { app, net, protocol } = require('electron')
|
||||||
import { join } from 'path'
|
const { join } = require('path')
|
||||||
import { pathToFileURL } from 'url'
|
const { pathToFileURL } = require('url')
|
||||||
|
|
||||||
protocol.registerSchemesAsPrivileged([
|
protocol.registerSchemesAsPrivileged([
|
||||||
{
|
{
|
||||||
|
@ -131,7 +131,7 @@ protocol.registerSchemesAsPrivileged([
|
||||||
privileges: {
|
privileges: {
|
||||||
standard: true,
|
standard: true,
|
||||||
secure: true,
|
secure: true,
|
||||||
supportsFetchAPI: true
|
supportFetchAPI: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@ -147,7 +147,7 @@ app.whenReady().then(() => {
|
||||||
}
|
}
|
||||||
// NB, this does not check for paths that escape the bundle, e.g.
|
// NB, this does not check for paths that escape the bundle, e.g.
|
||||||
// app://bundle/../../secret_file.txt
|
// app://bundle/../../secret_file.txt
|
||||||
return net.fetch(pathToFileURL(join(__dirname, pathname)))
|
return net.fetch(pathToFileURL(join(__dirname, pathname)).toString())
|
||||||
} else if (host === 'api') {
|
} else if (host === 'api') {
|
||||||
return net.fetch('https://api.my-server.com/' + pathname, {
|
return net.fetch('https://api.my-server.com/' + pathname, {
|
||||||
method: req.method,
|
method: req.method,
|
||||||
|
|
|
@ -98,7 +98,7 @@ Emitted when Electron is about to download `item` in `webContents`.
|
||||||
Calling `event.preventDefault()` will cancel the download and `item` will not be
|
Calling `event.preventDefault()` will cancel the download and `item` will not be
|
||||||
available from next tick of the process.
|
available from next tick of the process.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[4]
|
||||||
const { session } = require('electron')
|
const { session } = require('electron')
|
||||||
session.defaultSession.on('will-download', (event, item, webContents) => {
|
session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -214,7 +214,7 @@ cancel the request. Additionally, permissioning on `navigator.hid` can
|
||||||
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
||||||
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||||
const { app, BrowserWindow } = require('electron')
|
const { app, BrowserWindow } = require('electron')
|
||||||
|
|
||||||
let win = null
|
let win = null
|
||||||
|
@ -253,7 +253,7 @@ app.whenReady().then(() => {
|
||||||
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const selectedDevice = details.deviceList.find((device) => {
|
const selectedDevice = details.deviceList.find((device) => {
|
||||||
return device.vendorId === '9025' && device.productId === '67'
|
return device.vendorId === 9025 && device.productId === 67
|
||||||
})
|
})
|
||||||
callback(selectedDevice?.deviceId)
|
callback(selectedDevice?.deviceId)
|
||||||
})
|
})
|
||||||
|
@ -320,7 +320,7 @@ cancel the request. Additionally, permissioning on `navigator.serial` can
|
||||||
be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
|
be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
|
||||||
with the `serial` permission.
|
with the `serial` permission.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||||
const { app, BrowserWindow } = require('electron')
|
const { app, BrowserWindow } = require('electron')
|
||||||
|
|
||||||
let win = null
|
let win = null
|
||||||
|
@ -463,7 +463,7 @@ cancel the request. Additionally, permissioning on `navigator.usb` can
|
||||||
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
||||||
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)} @ts-type={updateGrantedDevices:(devices:Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)=>void}
|
||||||
const { app, BrowserWindow } = require('electron')
|
const { app, BrowserWindow } = require('electron')
|
||||||
|
|
||||||
let win = null
|
let win = null
|
||||||
|
@ -502,7 +502,7 @@ app.whenReady().then(() => {
|
||||||
win.webContents.session.on('select-usb-device', (event, details, callback) => {
|
win.webContents.session.on('select-usb-device', (event, details, callback) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const selectedDevice = details.deviceList.find((device) => {
|
const selectedDevice = details.deviceList.find((device) => {
|
||||||
return device.vendorId === '9025' && device.productId === '67'
|
return device.vendorId === 9025 && device.productId === 67
|
||||||
})
|
})
|
||||||
if (selectedDevice) {
|
if (selectedDevice) {
|
||||||
// Optionally, add this to the persisted devices (updateGrantedDevices needs to be implemented by developer to persist permissions)
|
// Optionally, add this to the persisted devices (updateGrantedDevices needs to be implemented by developer to persist permissions)
|
||||||
|
@ -755,15 +755,17 @@ Sets download saving directory. By default, the download directory will be the
|
||||||
Emulates network with the given configuration for the `session`.
|
Emulates network with the given configuration for the `session`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
|
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
|
||||||
window.webContents.session.enableNetworkEmulation({
|
win.webContents.session.enableNetworkEmulation({
|
||||||
latency: 500,
|
latency: 500,
|
||||||
downloadThroughput: 6400,
|
downloadThroughput: 6400,
|
||||||
uploadThroughput: 6400
|
uploadThroughput: 6400
|
||||||
})
|
})
|
||||||
|
|
||||||
// To emulate a network outage.
|
// To emulate a network outage.
|
||||||
window.webContents.session.enableNetworkEmulation({ offline: true })
|
win.webContents.session.enableNetworkEmulation({ offline: true })
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `ses.preconnect(options)`
|
#### `ses.preconnect(options)`
|
||||||
|
@ -1036,7 +1038,7 @@ Additionally, the default behavior of Electron is to store granted device permis
|
||||||
If longer term storage is needed, a developer can store granted device
|
If longer term storage is needed, a developer can store granted device
|
||||||
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
|
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||||
const { app, BrowserWindow } = require('electron')
|
const { app, BrowserWindow } = require('electron')
|
||||||
|
|
||||||
let win = null
|
let win = null
|
||||||
|
@ -1084,9 +1086,9 @@ app.whenReady().then(() => {
|
||||||
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const selectedDevice = details.deviceList.find((device) => {
|
const selectedDevice = details.deviceList.find((device) => {
|
||||||
return device.vendorId === '9025' && device.productId === '67'
|
return device.vendorId === 9025 && device.productId === 67
|
||||||
})
|
})
|
||||||
callback(selectedPort?.deviceId)
|
callback(selectedDevice?.deviceId)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -1174,23 +1176,17 @@ macOS does not require a handler because macOS handles the pairing
|
||||||
automatically. To clear the handler, call `setBluetoothPairingHandler(null)`.
|
automatically. To clear the handler, call `setBluetoothPairingHandler(null)`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
const { app, BrowserWindow, session } = require('electron')
|
||||||
const { app, BrowserWindow, ipcMain, session } = require('electron')
|
const path = require('path')
|
||||||
|
|
||||||
let bluetoothPinCallback = null
|
|
||||||
|
|
||||||
function createWindow () {
|
function createWindow () {
|
||||||
|
let bluetoothPinCallback = null
|
||||||
|
|
||||||
const mainWindow = new BrowserWindow({
|
const mainWindow = new BrowserWindow({
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(__dirname, 'preload.js')
|
preload: path.join(__dirname, 'preload.js')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// Listen for an IPC message from the renderer to get the response for the Bluetooth pairing.
|
|
||||||
ipcMain.on('bluetooth-pairing-response', (event, response) => {
|
|
||||||
bluetoothPinCallback(response)
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
|
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
|
||||||
bluetoothPinCallback = callback
|
bluetoothPinCallback = callback
|
||||||
|
@ -1200,6 +1196,12 @@ mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) =>
|
||||||
mainWindow.webContents.send('bluetooth-pairing-request', details)
|
mainWindow.webContents.send('bluetooth-pairing-request', details)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Listen for an IPC message from the renderer to get the response for the Bluetooth pairing.
|
||||||
|
mainWindow.webContents.ipc.on('bluetooth-pairing-response', (event, response) => {
|
||||||
|
bluetoothPinCallback(response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow()
|
createWindow()
|
||||||
})
|
})
|
||||||
|
|
|
@ -87,12 +87,12 @@ const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar
|
||||||
let spinning = false
|
let spinning = false
|
||||||
|
|
||||||
// Reel labels
|
// Reel labels
|
||||||
const reel1 = new TouchBarLabel()
|
const reel1 = new TouchBarLabel({ label: '' })
|
||||||
const reel2 = new TouchBarLabel()
|
const reel2 = new TouchBarLabel({ label: '' })
|
||||||
const reel3 = new TouchBarLabel()
|
const reel3 = new TouchBarLabel({ label: '' })
|
||||||
|
|
||||||
// Spin result label
|
// Spin result label
|
||||||
const result = new TouchBarLabel()
|
const result = new TouchBarLabel({ label: '' })
|
||||||
|
|
||||||
// Spin button
|
// Spin button
|
||||||
const spin = new TouchBarButton({
|
const spin = new TouchBarButton({
|
||||||
|
|
|
@ -98,7 +98,7 @@ async function lookupTargetId (browserWindow) {
|
||||||
await wc.debugger.attach('1.3')
|
await wc.debugger.attach('1.3')
|
||||||
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
|
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
|
||||||
const { targetId } = targetInfo
|
const { targetId } = targetInfo
|
||||||
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
|
const targetWebContents = await wc.fromDevToolsTargetId(targetId)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1020,9 +1020,9 @@ e.g. the `http://` or `file://`. If the load should bypass http cache then
|
||||||
use the `pragma` header to achieve it.
|
use the `pragma` header to achieve it.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { webContents } = require('electron')
|
const win = new BrowserWindow()
|
||||||
const options = { extraHeaders: 'pragma: no-cache\n' }
|
const options = { extraHeaders: 'pragma: no-cache\n' }
|
||||||
webContents.loadURL('https://github.com', options)
|
win.webContents.loadURL('https://github.com', options)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `contents.loadFile(filePath[, options])`
|
#### `contents.loadFile(filePath[, options])`
|
||||||
|
@ -1052,6 +1052,7 @@ an app structure like this:
|
||||||
Would require code like this
|
Would require code like this
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
const win = new BrowserWindow()
|
||||||
win.loadFile('src/index.html')
|
win.loadFile('src/index.html')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1188,7 +1189,9 @@ when this process is unstable or unusable, for instance in order to recover
|
||||||
from the `unresponsive` event.
|
from the `unresponsive` event.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
contents.on('unresponsive', async () => {
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
|
win.webContents.on('unresponsive', async () => {
|
||||||
const { response } = await dialog.showMessageBox({
|
const { response } = await dialog.showMessageBox({
|
||||||
message: 'App X has become unresponsive',
|
message: 'App X has become unresponsive',
|
||||||
title: 'Do you want to try forcefully reloading the app?',
|
title: 'Do you want to try forcefully reloading the app?',
|
||||||
|
@ -1196,8 +1199,8 @@ contents.on('unresponsive', async () => {
|
||||||
cancelId: 1
|
cancelId: 1
|
||||||
})
|
})
|
||||||
if (response === 0) {
|
if (response === 0) {
|
||||||
contents.forcefullyCrashRenderer()
|
win.webContents.forcefullyCrashRenderer()
|
||||||
contents.reload()
|
win.webContents.reload()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -1224,8 +1227,9 @@ Injects CSS into the current web page and returns a unique key for the inserted
|
||||||
stylesheet.
|
stylesheet.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
contents.on('did-finish-load', () => {
|
const win = new BrowserWindow()
|
||||||
contents.insertCSS('html, body { background-color: #f00; }')
|
win.webContents.on('did-finish-load', () => {
|
||||||
|
win.webContents.insertCSS('html, body { background-color: #f00; }')
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1239,9 +1243,11 @@ Removes the inserted CSS from the current web page. The stylesheet is identified
|
||||||
by its key, which is returned from `contents.insertCSS(css)`.
|
by its key, which is returned from `contents.insertCSS(css)`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
contents.on('did-finish-load', async () => {
|
const win = new BrowserWindow()
|
||||||
const key = await contents.insertCSS('html, body { background-color: #f00; }')
|
|
||||||
contents.removeInsertedCSS(key)
|
win.webContents.on('did-finish-load', async () => {
|
||||||
|
const key = await win.webContents.insertCSS('html, body { background-color: #f00; }')
|
||||||
|
win.webContents.removeInsertedCSS(key)
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1262,7 +1268,9 @@ this limitation.
|
||||||
Code execution will be suspended until web page stop loading.
|
Code execution will be suspended until web page stop loading.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true)
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
|
win.webContents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
console.log(result) // Will be the JSON object from the fetch call
|
console.log(result) // Will be the JSON object from the fetch call
|
||||||
})
|
})
|
||||||
|
@ -1373,7 +1381,8 @@ Sets the maximum and minimum pinch-to-zoom level.
|
||||||
> **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call:
|
> **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call:
|
||||||
>
|
>
|
||||||
> ```js
|
> ```js
|
||||||
> contents.setVisualZoomLevelLimits(1, 3)
|
> const win = new BrowserWindow()
|
||||||
|
> win.webContents.setVisualZoomLevelLimits(1, 3)
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
#### `contents.undo()`
|
#### `contents.undo()`
|
||||||
|
@ -1508,12 +1517,12 @@ can be obtained by subscribing to [`found-in-page`](web-contents.md#event-found-
|
||||||
Stops any `findInPage` request for the `webContents` with the provided `action`.
|
Stops any `findInPage` request for the `webContents` with the provided `action`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { webContents } = require('electron')
|
const win = new BrowserWindow()
|
||||||
webContents.on('found-in-page', (event, result) => {
|
win.webContents.on('found-in-page', (event, result) => {
|
||||||
if (result.finalUpdate) webContents.stopFindInPage('clearSelection')
|
if (result.finalUpdate) win.webContents.stopFindInPage('clearSelection')
|
||||||
})
|
})
|
||||||
|
|
||||||
const requestId = webContents.findInPage('api')
|
const requestId = win.webContents.findInPage('api')
|
||||||
console.log(requestId)
|
console.log(requestId)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1593,6 +1602,7 @@ Use `page-break-before: always;` CSS style to force to print to a new page.
|
||||||
Example usage:
|
Example usage:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
const win = new BrowserWindow()
|
||||||
const options = {
|
const options = {
|
||||||
silent: true,
|
silent: true,
|
||||||
deviceName: 'My-Printer',
|
deviceName: 'My-Printer',
|
||||||
|
@ -1889,8 +1899,9 @@ For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Main process
|
// Main process
|
||||||
|
const win = new BrowserWindow()
|
||||||
const { port1, port2 } = new MessageChannelMain()
|
const { port1, port2 } = new MessageChannelMain()
|
||||||
webContents.postMessage('port', { message: 'hello' }, [port1])
|
win.webContents.postMessage('port', { message: 'hello' }, [port1])
|
||||||
|
|
||||||
// Renderer process
|
// Renderer process
|
||||||
ipcRenderer.on('port', (e, msg) => {
|
ipcRenderer.on('port', (e, msg) => {
|
||||||
|
|
|
@ -128,8 +128,9 @@ For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Main process
|
// Main process
|
||||||
|
const win = new BrowserWindow()
|
||||||
const { port1, port2 } = new MessageChannelMain()
|
const { port1, port2 } = new MessageChannelMain()
|
||||||
webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
|
win.webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
|
||||||
|
|
||||||
// Renderer process
|
// Renderer process
|
||||||
ipcRenderer.on('port', (e, msg) => {
|
ipcRenderer.on('port', (e, msg) => {
|
||||||
|
|
|
@ -96,13 +96,12 @@ with an array of misspelt words when complete.
|
||||||
|
|
||||||
An example of using [node-spellchecker][spellchecker] as provider:
|
An example of using [node-spellchecker][spellchecker] as provider:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[2,6]
|
||||||
const { webFrame } = require('electron')
|
const { webFrame } = require('electron')
|
||||||
const spellChecker = require('spellchecker')
|
const spellChecker = require('spellchecker')
|
||||||
webFrame.setSpellCheckProvider('en-US', {
|
webFrame.setSpellCheckProvider('en-US', {
|
||||||
spellCheck (words, callback) {
|
spellCheck (words, callback) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const spellchecker = require('spellchecker')
|
|
||||||
const misspelled = words.filter(x => spellchecker.isMisspelled(x))
|
const misspelled = words.filter(x => spellchecker.isMisspelled(x))
|
||||||
callback(misspelled)
|
callback(misspelled)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
|
@ -255,7 +255,7 @@ The `webview` tag has the following methods:
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[3]
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
webview.addEventListener('dom-ready', () => {
|
webview.addEventListener('dom-ready', () => {
|
||||||
webview.openDevTools()
|
webview.openDevTools()
|
||||||
|
@ -799,7 +799,7 @@ Fired when the guest window logs a console message.
|
||||||
The following example code forwards all log messages to the embedder's console
|
The following example code forwards all log messages to the embedder's console
|
||||||
without regard for log level or other properties.
|
without regard for log level or other properties.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[3]
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
webview.addEventListener('console-message', (e) => {
|
webview.addEventListener('console-message', (e) => {
|
||||||
console.log('Guest page logged a message:', e.message)
|
console.log('Guest page logged a message:', e.message)
|
||||||
|
@ -820,7 +820,7 @@ Returns:
|
||||||
Fired when a result is available for
|
Fired when a result is available for
|
||||||
[`webview.findInPage`](#webviewfindinpagetext-options) request.
|
[`webview.findInPage`](#webviewfindinpagetext-options) request.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[3,6]
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
webview.addEventListener('found-in-page', (e) => {
|
webview.addEventListener('found-in-page', (e) => {
|
||||||
webview.stopFindInPage('keepSelection')
|
webview.stopFindInPage('keepSelection')
|
||||||
|
@ -945,7 +945,7 @@ Fired when the guest page attempts to close itself.
|
||||||
The following example code navigates the `webview` to `about:blank` when the
|
The following example code navigates the `webview` to `about:blank` when the
|
||||||
guest attempts to close itself.
|
guest attempts to close itself.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[3]
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
webview.addEventListener('close', () => {
|
webview.addEventListener('close', () => {
|
||||||
webview.src = 'about:blank'
|
webview.src = 'about:blank'
|
||||||
|
@ -965,7 +965,7 @@ Fired when the guest page has sent an asynchronous message to embedder page.
|
||||||
With `sendToHost` method and `ipc-message` event you can communicate
|
With `sendToHost` method and `ipc-message` event you can communicate
|
||||||
between guest page and embedder page:
|
between guest page and embedder page:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[4,7]
|
||||||
// In embedder page.
|
// In embedder page.
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
webview.addEventListener('ipc-message', (event) => {
|
webview.addEventListener('ipc-message', (event) => {
|
||||||
|
|
|
@ -55,7 +55,7 @@ fs.readdirSync('/path/to/example.asar')
|
||||||
|
|
||||||
Use a module from the archive:
|
Use a module from the archive:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
require('./path/to/example.asar/dir/module.js')
|
require('./path/to/example.asar/dir/module.js')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of t
|
||||||
|
|
||||||
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
|
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
|
||||||
|
|
||||||
```js
|
```js @ts-nocheck
|
||||||
require('@electron/fuses').flipFuses(
|
require('@electron/fuses').flipFuses(
|
||||||
// E.g. /a/b/Foo.app
|
// E.g. /a/b/Foo.app
|
||||||
pathToPackagedApp,
|
pathToPackagedApp,
|
||||||
|
|
|
@ -90,7 +90,7 @@ Usage of `selenium-webdriver` with Electron is the same as with
|
||||||
normal websites, except that you have to manually specify how to connect
|
normal websites, except that you have to manually specify how to connect
|
||||||
ChromeDriver and where to find the binary of your Electron app:
|
ChromeDriver and where to find the binary of your Electron app:
|
||||||
|
|
||||||
```js title='test.js'
|
```js title='test.js' @ts-expect-error=[1]
|
||||||
const webdriver = require('selenium-webdriver')
|
const webdriver = require('selenium-webdriver')
|
||||||
const driver = new webdriver.Builder()
|
const driver = new webdriver.Builder()
|
||||||
// The "9515" is the port opened by ChromeDriver.
|
// The "9515" is the port opened by ChromeDriver.
|
||||||
|
@ -155,7 +155,7 @@ Playwright launches your app in development mode through the `_electron.launch`
|
||||||
To point this API to your Electron app, you can pass the path to your main process
|
To point this API to your Electron app, you can pass the path to your main process
|
||||||
entry point (here, it is `main.js`).
|
entry point (here, it is `main.js`).
|
||||||
|
|
||||||
```js {5}
|
```js {5} @ts-nocheck
|
||||||
const { _electron: electron } = require('playwright')
|
const { _electron: electron } = require('playwright')
|
||||||
const { test } = require('@playwright/test')
|
const { test } = require('@playwright/test')
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ test('launch app', async () => {
|
||||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||||
is a powerful class that has access to main process modules for example:
|
is a powerful class that has access to main process modules for example:
|
||||||
|
|
||||||
```js {6-11}
|
```js {6-11} @ts-nocheck
|
||||||
const { _electron: electron } = require('playwright')
|
const { _electron: electron } = require('playwright')
|
||||||
const { test } = require('@playwright/test')
|
const { test } = require('@playwright/test')
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ test('get isPackaged', async () => {
|
||||||
It can also create individual [Page][playwright-page] objects from Electron BrowserWindow instances.
|
It can also create individual [Page][playwright-page] objects from Electron BrowserWindow instances.
|
||||||
For example, to grab the first BrowserWindow and save a screenshot:
|
For example, to grab the first BrowserWindow and save a screenshot:
|
||||||
|
|
||||||
```js {6-7}
|
```js {6-7} @ts-nocheck
|
||||||
const { _electron: electron } = require('playwright')
|
const { _electron: electron } = require('playwright')
|
||||||
const { test } = require('@playwright/test')
|
const { test } = require('@playwright/test')
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ test('save screenshot', async () => {
|
||||||
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
|
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
|
||||||
test file with a single test and assertion:
|
test file with a single test and assertion:
|
||||||
|
|
||||||
```js title='example.spec.js'
|
```js title='example.spec.js' @ts-nocheck
|
||||||
const { _electron: electron } = require('playwright')
|
const { _electron: electron } = require('playwright')
|
||||||
const { test, expect } = require('@playwright/test')
|
const { test, expect } = require('@playwright/test')
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ expose custom methods to your test suite.
|
||||||
To create a custom driver, we'll use Node.js' [`child_process`](https://nodejs.org/api/child_process.html) API.
|
To create a custom driver, we'll use Node.js' [`child_process`](https://nodejs.org/api/child_process.html) API.
|
||||||
The test suite will spawn the Electron process, then establish a simple messaging protocol:
|
The test suite will spawn the Electron process, then establish a simple messaging protocol:
|
||||||
|
|
||||||
```js title='testDriver.js'
|
```js title='testDriver.js' @ts-nocheck
|
||||||
const childProcess = require('child_process')
|
const childProcess = require('child_process')
|
||||||
const electronPath = require('electron')
|
const electronPath = require('electron')
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ For convenience, you may want to wrap `appProcess` in a driver object that provi
|
||||||
high-level functions. Here is an example of how you can do this. Let's start by creating
|
high-level functions. Here is an example of how you can do this. Let's start by creating
|
||||||
a `TestDriver` class:
|
a `TestDriver` class:
|
||||||
|
|
||||||
```js title='testDriver.js'
|
```js title='testDriver.js' @ts-nocheck
|
||||||
class TestDriver {
|
class TestDriver {
|
||||||
constructor ({ path, args, env }) {
|
constructor ({ path, args, env }) {
|
||||||
this.rpcCalls = []
|
this.rpcCalls = []
|
||||||
|
@ -378,7 +378,7 @@ framework of your choosing. The following example uses
|
||||||
[`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest
|
[`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest
|
||||||
or Mocha would work as well:
|
or Mocha would work as well:
|
||||||
|
|
||||||
```js title='test.js'
|
```js title='test.js' @ts-nocheck
|
||||||
const test = require('ava')
|
const test = require('ava')
|
||||||
const electronPath = require('electron')
|
const electronPath = require('electron')
|
||||||
const { TestDriver } = require('./testDriver')
|
const { TestDriver } = require('./testDriver')
|
||||||
|
|
|
@ -67,7 +67,7 @@ are likely using [`electron-packager`][], which includes [`@electron/osx-sign`][
|
||||||
If you're using Packager's API, you can pass [in configuration that both signs
|
If you're using Packager's API, you can pass [in configuration that both signs
|
||||||
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||||
|
|
||||||
```js
|
```js @ts-nocheck
|
||||||
const packager = require('electron-packager')
|
const packager = require('electron-packager')
|
||||||
|
|
||||||
packager({
|
packager({
|
||||||
|
@ -116,7 +116,7 @@ Electron app. This is the tool used under the hood by Electron Forge's
|
||||||
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
||||||
options when creating your installer.
|
options when creating your installer.
|
||||||
|
|
||||||
```js {10-11}
|
```js {10-11} @ts-nocheck
|
||||||
const electronInstaller = require('electron-winstaller')
|
const electronInstaller = require('electron-winstaller')
|
||||||
// NB: Use this syntax within an async function, Node does not have support for
|
// NB: Use this syntax within an async function, Node does not have support for
|
||||||
// top-level await as of Node 12.
|
// top-level await as of Node 12.
|
||||||
|
@ -146,7 +146,7 @@ If you're not using Electron Forge and want to use `electron-wix-msi` directly,
|
||||||
`certificateFile` and `certificatePassword` configuration options
|
`certificateFile` and `certificatePassword` configuration options
|
||||||
or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option.
|
or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option.
|
||||||
|
|
||||||
```js {12-13}
|
```js {12-13} @ts-nocheck
|
||||||
import { MSICreator } from 'electron-wix-msi'
|
import { MSICreator } from 'electron-wix-msi'
|
||||||
|
|
||||||
// Step 1: Instantiate the MSICreator
|
// Step 1: Instantiate the MSICreator
|
||||||
|
|
|
@ -16,7 +16,7 @@ Context isolation has been enabled by default since Electron 12, and it is a rec
|
||||||
|
|
||||||
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
|
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
|
||||||
|
|
||||||
```javascript title='preload.js'
|
```javascript title='preload.js' @ts-nocheck
|
||||||
// preload with contextIsolation disabled
|
// preload with contextIsolation disabled
|
||||||
window.myAPI = {
|
window.myAPI = {
|
||||||
doAThing: () => {}
|
doAThing: () => {}
|
||||||
|
@ -25,7 +25,7 @@ window.myAPI = {
|
||||||
|
|
||||||
The `doAThing()` function could then be used directly in the renderer process:
|
The `doAThing()` function could then be used directly in the renderer process:
|
||||||
|
|
||||||
```javascript title='renderer.js'
|
```javascript title='renderer.js' @ts-nocheck
|
||||||
// use the exposed API in the renderer
|
// use the exposed API in the renderer
|
||||||
window.myAPI.doAThing()
|
window.myAPI.doAThing()
|
||||||
```
|
```
|
||||||
|
@ -43,7 +43,7 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript title='renderer.js'
|
```javascript title='renderer.js' @ts-nocheck
|
||||||
// use the exposed API in the renderer
|
// use the exposed API in the renderer
|
||||||
window.myAPI.doAThing()
|
window.myAPI.doAThing()
|
||||||
```
|
```
|
||||||
|
@ -98,7 +98,7 @@ declare global {
|
||||||
|
|
||||||
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
|
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
|
||||||
|
|
||||||
```typescript title='renderer.ts'
|
```typescript title='renderer.ts' @ts-nocheck
|
||||||
window.electronAPI.loadPreferences()
|
window.electronAPI.loadPreferences()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ Now the renderer process can communicate with the main process securely and perf
|
||||||
|
|
||||||
The `renderer.js` file is responsible for controlling the `<button>` functionality.
|
The `renderer.js` file is responsible for controlling the `<button>` functionality.
|
||||||
|
|
||||||
```js title='renderer.js'
|
```js title='renderer.js' @ts-expect-error=[2,7]
|
||||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||||
const isDarkMode = await window.darkMode.toggle()
|
const isDarkMode = await window.darkMode.toggle()
|
||||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||||
|
|
|
@ -67,7 +67,7 @@ The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is
|
||||||
|
|
||||||
We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
|
We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
|
||||||
|
|
||||||
```js
|
```js @ts-nocheck
|
||||||
require('@electron/fuses').flipFuses(
|
require('@electron/fuses').flipFuses(
|
||||||
// Path to electron
|
// Path to electron
|
||||||
require('electron'),
|
require('electron'),
|
||||||
|
|
|
@ -66,7 +66,7 @@ You can use environment variables to override the base URL, the path at which to
|
||||||
look for Electron binaries, and the binary filename. The URL used by `@electron/get`
|
look for Electron binaries, and the binary filename. The URL used by `@electron/get`
|
||||||
is composed as follows:
|
is composed as follows:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
|
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ To make these elements interactive, we'll be adding a few lines of code in the i
|
||||||
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
|
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
|
||||||
script:
|
script:
|
||||||
|
|
||||||
```javascript title='renderer.js (Renderer Process)'
|
```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[4,5]
|
||||||
const setButton = document.getElementById('btn')
|
const setButton = document.getElementById('btn')
|
||||||
const titleInput = document.getElementById('title')
|
const titleInput = document.getElementById('title')
|
||||||
setButton.addEventListener('click', () => {
|
setButton.addEventListener('click', () => {
|
||||||
|
@ -182,13 +182,13 @@ provided to the renderer process. Please refer to
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```javascript {6-13,25} title='main.js (Main Process)'
|
```javascript {6-13,25} title='main.js (Main Process)'
|
||||||
const { BrowserWindow, dialog, ipcMain } = require('electron')
|
const { app, BrowserWindow, dialog, ipcMain } = require('electron')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
async function handleFileOpen () {
|
async function handleFileOpen () {
|
||||||
const { canceled, filePaths } = await dialog.showOpenDialog()
|
const { canceled, filePaths } = await dialog.showOpenDialog({})
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
return filePaths[0]
|
return filePaths[0]
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ function createWindow () {
|
||||||
mainWindow.loadFile('index.html')
|
mainWindow.loadFile('index.html')
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady(() => {
|
app.whenReady().then(() => {
|
||||||
ipcMain.handle('dialog:openFile', handleFileOpen)
|
ipcMain.handle('dialog:openFile', handleFileOpen)
|
||||||
createWindow()
|
createWindow()
|
||||||
})
|
})
|
||||||
|
@ -263,7 +263,7 @@ The UI consists of a single `#btn` button element that will be used to trigger o
|
||||||
a `#filePath` element that will be used to display the path of the selected file. Making these
|
a `#filePath` element that will be used to display the path of the selected file. Making these
|
||||||
pieces work will take a few lines of code in the renderer process script:
|
pieces work will take a few lines of code in the renderer process script:
|
||||||
|
|
||||||
```javascript title='renderer.js (Renderer Process)'
|
```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[5]
|
||||||
const btn = document.getElementById('btn')
|
const btn = document.getElementById('btn')
|
||||||
const filePathElement = document.getElementById('filePath')
|
const filePathElement = document.getElementById('filePath')
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ function createWindow () {
|
||||||
For the purposes of the tutorial, it's important to note that the `click` handler
|
For the purposes of the tutorial, it's important to note that the `click` handler
|
||||||
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
|
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
click: () => mainWindow.webContents.send('update-counter', -1)
|
click: () => mainWindow.webContents.send('update-counter', -1)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -486,7 +486,7 @@ To tie it all together, we'll create an interface in the loaded HTML file that c
|
||||||
Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation
|
Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation
|
||||||
so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.
|
so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.
|
||||||
|
|
||||||
```javascript title='renderer.js (Renderer Process)'
|
```javascript title='renderer.js (Renderer Process)' @ts-nocheck
|
||||||
const counter = document.getElementById('counter')
|
const counter = document.getElementById('counter')
|
||||||
|
|
||||||
window.electronAPI.onUpdateCounter((_event, value) => {
|
window.electronAPI.onUpdateCounter((_event, value) => {
|
||||||
|
@ -509,7 +509,7 @@ We can demonstrate this with slight modifications to the code from the previous
|
||||||
renderer process, use the `event` parameter to send a reply back to the main process through the
|
renderer process, use the `event` parameter to send a reply back to the main process through the
|
||||||
`counter-value` channel.
|
`counter-value` channel.
|
||||||
|
|
||||||
```javascript title='renderer.js (Renderer Process)'
|
```javascript title='renderer.js (Renderer Process)' @ts-nocheck
|
||||||
const counter = document.getElementById('counter')
|
const counter = document.getElementById('counter')
|
||||||
|
|
||||||
window.electronAPI.onUpdateCounter((event, value) => {
|
window.electronAPI.onUpdateCounter((event, value) => {
|
||||||
|
|
|
@ -56,7 +56,7 @@ Starting with a working application from the
|
||||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||||
following lines:
|
following lines:
|
||||||
|
|
||||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global'
|
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global' @ts-type={createWindow:()=>void}
|
||||||
const { app, globalShortcut } = require('electron')
|
const { app, globalShortcut } = require('electron')
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
|
@ -131,7 +131,7 @@ If you don't want to do manual shortcut parsing, there are libraries that do
|
||||||
advanced key detection, such as [mousetrap][]. Below are examples of usage of the
|
advanced key detection, such as [mousetrap][]. Below are examples of usage of the
|
||||||
`mousetrap` running in the Renderer process:
|
`mousetrap` running in the Renderer process:
|
||||||
|
|
||||||
```js
|
```js @ts-nocheck
|
||||||
Mousetrap.bind('4', () => { console.log('4') })
|
Mousetrap.bind('4', () => { console.log('4') })
|
||||||
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
|
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
|
||||||
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')
|
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')
|
||||||
|
|
|
@ -45,6 +45,8 @@ if (process.defaultApp) {
|
||||||
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
let mainWindow
|
||||||
|
|
||||||
const createWindow = () => {
|
const createWindow = () => {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
|
@ -65,7 +67,7 @@ This code will be different in Windows compared to MacOS and Linux. This is due
|
||||||
|
|
||||||
#### Windows code:
|
#### Windows code:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={mainWindow:Electron.BrowserWindow} @ts-type={createWindow:()=>void}
|
||||||
const gotTheLock = app.requestSingleInstanceLock()
|
const gotTheLock = app.requestSingleInstanceLock()
|
||||||
|
|
||||||
if (!gotTheLock) {
|
if (!gotTheLock) {
|
||||||
|
@ -91,7 +93,7 @@ if (!gotTheLock) {
|
||||||
|
|
||||||
#### MacOS and Linux code:
|
#### MacOS and Linux code:
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-type={createWindow:()=>void}
|
||||||
// This method will be called when Electron has finished
|
// This method will be called when Electron has finished
|
||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
// Some APIs can only be used after this event occurs.
|
// Some APIs can only be used after this event occurs.
|
||||||
|
@ -166,7 +168,7 @@ If you're using Electron Packager's API, adding support for protocol handlers is
|
||||||
Electron Forge is handled, except
|
Electron Forge is handled, except
|
||||||
`protocols` is part of the Packager options passed to the `packager` function.
|
`protocols` is part of the Packager options passed to the `packager` function.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-nocheck
|
||||||
const packager = require('electron-packager')
|
const packager = require('electron-packager')
|
||||||
|
|
||||||
packager({
|
packager({
|
||||||
|
|
|
@ -126,7 +126,7 @@ app.whenReady().then(async () => {
|
||||||
Then, in your preload scripts you receive the port through IPC and set up the
|
Then, in your preload scripts you receive the port through IPC and set up the
|
||||||
listeners.
|
listeners.
|
||||||
|
|
||||||
```js title='preloadMain.js and preloadSecondary.js (Preload scripts)'
|
```js title='preloadMain.js and preloadSecondary.js (Preload scripts)' @ts-nocheck
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
|
|
||||||
ipcRenderer.on('port', e => {
|
ipcRenderer.on('port', e => {
|
||||||
|
@ -148,7 +148,7 @@ That means window.electronMessagePort is globally available and you can call
|
||||||
`postMessage` on it from anywhere in your app to send a message to the other
|
`postMessage` on it from anywhere in your app to send a message to the other
|
||||||
renderer.
|
renderer.
|
||||||
|
|
||||||
```js title='renderer.js (Renderer Process)'
|
```js title='renderer.js (Renderer Process)' @ts-nocheck
|
||||||
// elsewhere in your code to send a message to the other renderers message handler
|
// elsewhere in your code to send a message to the other renderers message handler
|
||||||
window.electronMessagePort.postmessage('ping')
|
window.electronMessagePort.postmessage('ping')
|
||||||
```
|
```
|
||||||
|
@ -181,7 +181,7 @@ app.whenReady().then(async () => {
|
||||||
// We can't use ipcMain.handle() here, because the reply needs to transfer a
|
// We can't use ipcMain.handle() here, because the reply needs to transfer a
|
||||||
// MessagePort.
|
// MessagePort.
|
||||||
// Listen for message sent from the top-level frame
|
// Listen for message sent from the top-level frame
|
||||||
mainWindow.webContents.mainFrame.on('request-worker-channel', (event) => {
|
mainWindow.webContents.mainFrame.ipc.on('request-worker-channel', (event) => {
|
||||||
// Create a new channel ...
|
// Create a new channel ...
|
||||||
const { port1, port2 } = new MessageChannelMain()
|
const { port1, port2 } = new MessageChannelMain()
|
||||||
// ... send one end to the worker ...
|
// ... send one end to the worker ...
|
||||||
|
@ -245,7 +245,7 @@ Electron's built-in IPC methods only support two modes: fire-and-forget
|
||||||
can implement a "response stream", where a single request responds with a
|
can implement a "response stream", where a single request responds with a
|
||||||
stream of data.
|
stream of data.
|
||||||
|
|
||||||
```js title='renderer.js (Renderer Process)'
|
```js title='renderer.js (Renderer Process)' @ts-expect-error=[18]
|
||||||
const makeStreamingRequest = (element, callback) => {
|
const makeStreamingRequest = (element, callback) => {
|
||||||
// MessageChannels are lightweight--it's cheap to create a new one for each
|
// MessageChannels are lightweight--it's cheap to create a new one for each
|
||||||
// request.
|
// request.
|
||||||
|
|
|
@ -42,7 +42,7 @@ safe.
|
||||||
The only way to load a native module safely for now, is to make sure the app
|
The only way to load a native module safely for now, is to make sure the app
|
||||||
loads no native modules after the Web Workers get started.
|
loads no native modules after the Web Workers get started.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[1]
|
||||||
process.dlopen = () => {
|
process.dlopen = () => {
|
||||||
throw new Error('Load native module is not safe')
|
throw new Error('Load native module is not safe')
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ In `preload.js` use the [`contextBridge`][] to inject a method `window.electron.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { contextBridge, ipcRenderer } = require('electron')
|
const { contextBridge, ipcRenderer } = require('electron')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electron', {
|
contextBridge.exposeInMainWorld('electron', {
|
||||||
startDrag: (fileName) => {
|
startDrag: (fileName) => {
|
||||||
|
@ -43,7 +44,7 @@ Add a draggable element to `index.html`, and reference your renderer script:
|
||||||
|
|
||||||
In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`][] above.
|
In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`][] above.
|
||||||
|
|
||||||
```javascript
|
```javascript @ts-expect-error=[3]
|
||||||
document.getElementById('drag').ondragstart = (event) => {
|
document.getElementById('drag').ondragstart = (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
window.electron.startDrag('drag-and-drop.md')
|
window.electron.startDrag('drag-and-drop.md')
|
||||||
|
|
|
@ -173,7 +173,7 @@ in the fictitious `.foo` format. In order to do that, it relies on the
|
||||||
equally fictitious `foo-parser` module. In traditional Node.js development,
|
equally fictitious `foo-parser` module. In traditional Node.js development,
|
||||||
you might write code that eagerly loads dependencies:
|
you might write code that eagerly loads dependencies:
|
||||||
|
|
||||||
```js title='parser.js'
|
```js title='parser.js' @ts-expect-error=[2]
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const fooParser = require('foo-parser')
|
const fooParser = require('foo-parser')
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ In the above example, we're doing a lot of work that's being executed as soon
|
||||||
as the file is loaded. Do we need to get parsed files right away? Could we
|
as the file is loaded. Do we need to get parsed files right away? Could we
|
||||||
do this work a little later, when `getParsedFiles()` is actually called?
|
do this work a little later, when `getParsedFiles()` is actually called?
|
||||||
|
|
||||||
```js title='parser.js'
|
```js title='parser.js' @ts-expect-error=[20]
|
||||||
// "fs" is likely already being loaded, so the `require()` call is cheap
|
// "fs" is likely already being loaded, so the `require()` call is cheap
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ class Parser {
|
||||||
// Touch the disk as soon as `getFiles` is called, not sooner.
|
// Touch the disk as soon as `getFiles` is called, not sooner.
|
||||||
// Also, ensure that we're not blocking other operations by using
|
// Also, ensure that we're not blocking other operations by using
|
||||||
// the asynchronous version.
|
// the asynchronous version.
|
||||||
this.files = this.files || await fs.readdir('.')
|
this.files = this.files || await fs.promises.readdir('.')
|
||||||
|
|
||||||
return this.files
|
return this.files
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,13 +175,13 @@ Although preload scripts share a `window` global with the renderer they're attac
|
||||||
you cannot directly attach any variables from the preload script to `window` because of
|
you cannot directly attach any variables from the preload script to `window` because of
|
||||||
the [`contextIsolation`][context-isolation] default.
|
the [`contextIsolation`][context-isolation] default.
|
||||||
|
|
||||||
```js title='preload.js'
|
```js title='preload.js' @ts-nocheck
|
||||||
window.myAPI = {
|
window.myAPI = {
|
||||||
desktop: true
|
desktop: true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js title='renderer.js'
|
```js title='renderer.js' @ts-nocheck
|
||||||
console.log(window.myAPI)
|
console.log(window.myAPI)
|
||||||
// => undefined
|
// => undefined
|
||||||
```
|
```
|
||||||
|
@ -200,7 +200,7 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
```js title='renderer.js'
|
```js title='renderer.js' @ts-nocheck
|
||||||
console.log(window.myAPI)
|
console.log(window.myAPI)
|
||||||
// => { desktop: true }
|
// => { desktop: true }
|
||||||
```
|
```
|
||||||
|
|
|
@ -182,7 +182,7 @@ In Electron, browser windows can only be created after the `app` module's
|
||||||
[`app.whenReady()`][app-when-ready] API. Call `createWindow()` after `whenReady()`
|
[`app.whenReady()`][app-when-ready] API. Call `createWindow()` after `whenReady()`
|
||||||
resolves its Promise.
|
resolves its Promise.
|
||||||
|
|
||||||
```js
|
```js @ts-type={createWindow:()=>void}
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow()
|
createWindow()
|
||||||
})
|
})
|
||||||
|
@ -239,7 +239,7 @@ from within your existing `whenReady()` callback.
|
||||||
|
|
||||||
[activate]: ../api/app.md#event-activate-macos
|
[activate]: ../api/app.md#event-activate-macos
|
||||||
|
|
||||||
```js
|
```js @ts-type={createWindow:()=>void}
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow()
|
createWindow()
|
||||||
|
|
||||||
|
@ -290,6 +290,7 @@ To attach this script to your renderer process, pass in the path to your preload
|
||||||
to the `webPreferences.preload` option in your existing `BrowserWindow` constructor.
|
to the `webPreferences.preload` option in your existing `BrowserWindow` constructor.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
const { app, BrowserWindow } = require('electron')
|
||||||
// include the Node.js 'path' module at the top of your file
|
// include the Node.js 'path' module at the top of your file
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
|
||||||
|
|
||||||
#### How?
|
#### How?
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)' @ts-type={browserWindow:Electron.BrowserWindow}
|
||||||
// Bad
|
// Bad
|
||||||
browserWindow.loadURL('http://example.com')
|
browserWindow.loadURL('http://example.com')
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ security-conscious developers might want to assume the very opposite.
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)'
|
||||||
const { session } = require('electron')
|
const { session } = require('electron')
|
||||||
const URL = require('url').URL
|
const { URL } = require('url')
|
||||||
|
|
||||||
session
|
session
|
||||||
.fromPartition('some-partition')
|
.fromPartition('some-partition')
|
||||||
|
@ -608,7 +608,8 @@ sometimes be fooled - a `startsWith('https://example.com')` test would let
|
||||||
`https://example.com.attacker.com` through.
|
`https://example.com.attacker.com` through.
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)'
|
||||||
const URL = require('url').URL
|
const { URL } = require('url')
|
||||||
|
const { app } = require('electron')
|
||||||
|
|
||||||
app.on('web-contents-created', (event, contents) => {
|
app.on('web-contents-created', (event, contents) => {
|
||||||
contents.on('will-navigate', (event, navigationUrl) => {
|
contents.on('will-navigate', (event, navigationUrl) => {
|
||||||
|
@ -647,8 +648,8 @@ receive, amongst other parameters, the `url` the window was requested to open
|
||||||
and the options used to create it. We recommend that you register a handler to
|
and the options used to create it. We recommend that you register a handler to
|
||||||
monitor the creation of windows, and deny any unexpected window creation.
|
monitor the creation of windows, and deny any unexpected window creation.
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)' @ts-type={isSafeForExternalOpen:(url:string)=>boolean}
|
||||||
const { shell } = require('electron')
|
const { app, shell } = require('electron')
|
||||||
|
|
||||||
app.on('web-contents-created', (event, contents) => {
|
app.on('web-contents-created', (event, contents) => {
|
||||||
contents.setWindowOpenHandler(({ url }) => {
|
contents.setWindowOpenHandler(({ url }) => {
|
||||||
|
@ -683,7 +684,7 @@ leveraged to execute arbitrary commands.
|
||||||
|
|
||||||
#### How?
|
#### How?
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)' @ts-type={USER_CONTROLLED_DATA_HERE:string}
|
||||||
// Bad
|
// Bad
|
||||||
const { shell } = require('electron')
|
const { shell } = require('electron')
|
||||||
shell.openExternal(USER_CONTROLLED_DATA_HERE)
|
shell.openExternal(USER_CONTROLLED_DATA_HERE)
|
||||||
|
@ -739,7 +740,7 @@ You should be validating the `sender` of **all** IPC messages by default.
|
||||||
|
|
||||||
#### How?
|
#### How?
|
||||||
|
|
||||||
```js title='main.js (Main Process)'
|
```js title='main.js (Main Process)' @ts-type={getSecrets:()=>unknown}
|
||||||
// Bad
|
// Bad
|
||||||
ipcMain.handle('get-secrets', () => {
|
ipcMain.handle('get-secrets', () => {
|
||||||
return getSecrets()
|
return getSecrets()
|
||||||
|
|
|
@ -72,7 +72,7 @@ npx electron-installer-snap --src=out/myappname-linux-x64
|
||||||
If you have an existing build pipeline, you can use `electron-installer-snap`
|
If you have an existing build pipeline, you can use `electron-installer-snap`
|
||||||
programmatically. For more information, see the [Snapcraft API docs][snapcraft-syntax].
|
programmatically. For more information, see the [Snapcraft API docs][snapcraft-syntax].
|
||||||
|
|
||||||
```js
|
```js @ts-nocheck
|
||||||
const snap = require('electron-installer-snap')
|
const snap = require('electron-installer-snap')
|
||||||
|
|
||||||
snap(options)
|
snap(options)
|
||||||
|
|
|
@ -20,12 +20,12 @@ On macOS as we use the native APIs there is no way to set the language that the
|
||||||
|
|
||||||
For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.
|
For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.
|
||||||
|
|
||||||
```js
|
```js @ts-type={myWindow:Electron.BrowserWindow}
|
||||||
// Sets the spellchecker to check English US and French
|
// Sets the spellchecker to check English US and French
|
||||||
myWindow.session.setSpellCheckerLanguages(['en-US', 'fr'])
|
myWindow.webContents.session.setSpellCheckerLanguages(['en-US', 'fr'])
|
||||||
|
|
||||||
// An array of all available language codes
|
// An array of all available language codes
|
||||||
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages
|
const possibleLanguages = myWindow.webContents.session.availableSpellCheckerLanguages
|
||||||
```
|
```
|
||||||
|
|
||||||
By default the spellchecker will enable the language matching the current OS locale.
|
By default the spellchecker will enable the language matching the current OS locale.
|
||||||
|
@ -35,7 +35,7 @@ By default the spellchecker will enable the language matching the current OS loc
|
||||||
All the required information to generate a context menu is provided in the [`context-menu`](../api/web-contents.md#event-context-menu) event on each `webContents` instance. A small example
|
All the required information to generate a context menu is provided in the [`context-menu`](../api/web-contents.md#event-context-menu) event on each `webContents` instance. A small example
|
||||||
of how to make a context menu with this information is provided below.
|
of how to make a context menu with this information is provided below.
|
||||||
|
|
||||||
```js
|
```js @ts-type={myWindow:Electron.BrowserWindow}
|
||||||
const { Menu, MenuItem } = require('electron')
|
const { Menu, MenuItem } = require('electron')
|
||||||
|
|
||||||
myWindow.webContents.on('context-menu', (event, params) => {
|
myWindow.webContents.on('context-menu', (event, params) => {
|
||||||
|
@ -45,7 +45,7 @@ myWindow.webContents.on('context-menu', (event, params) => {
|
||||||
for (const suggestion of params.dictionarySuggestions) {
|
for (const suggestion of params.dictionarySuggestions) {
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: suggestion,
|
label: suggestion,
|
||||||
click: () => mainWindow.webContents.replaceMisspelling(suggestion)
|
click: () => myWindow.webContents.replaceMisspelling(suggestion)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ myWindow.webContents.on('context-menu', (event, params) => {
|
||||||
menu.append(
|
menu.append(
|
||||||
new MenuItem({
|
new MenuItem({
|
||||||
label: 'Add to dictionary',
|
label: 'Add to dictionary',
|
||||||
click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
|
click: () => myWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,8 @@ myWindow.webContents.on('context-menu', (event, params) => {
|
||||||
|
|
||||||
Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from.
|
Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from.
|
||||||
|
|
||||||
```js
|
```js @ts-type={myWindow:Electron.BrowserWindow}
|
||||||
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
|
myWindow.webContents.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
|
||||||
```
|
```
|
||||||
|
|
||||||
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.
|
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.
|
||||||
|
|
|
@ -51,7 +51,7 @@ app.whenReady().then(() => {
|
||||||
|
|
||||||
Great! Now we can start attaching a context menu to our Tray, like so:
|
Great! Now we can start attaching a context menu to our Tray, like so:
|
||||||
|
|
||||||
```js
|
```js @ts-expect-error=[8]
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
{ label: 'Item1', type: 'radio' },
|
{ label: 'Item1', type: 'radio' },
|
||||||
{ label: 'Item2', type: 'radio' },
|
{ label: 'Item2', type: 'radio' },
|
||||||
|
@ -68,7 +68,7 @@ To read more about constructing native menus, click
|
||||||
|
|
||||||
Finally, let's give our tray a tooltip and a title.
|
Finally, let's give our tray a tooltip and a title.
|
||||||
|
|
||||||
```js
|
```js @ts-type={tray:Electron.Tray}
|
||||||
tray.setToolTip('This is my application')
|
tray.setToolTip('This is my application')
|
||||||
tray.setTitle('This is my title')
|
tray.setTitle('This is my title')
|
||||||
```
|
```
|
||||||
|
|
|
@ -256,7 +256,7 @@ const createWindow = () => {
|
||||||
|
|
||||||
### Calling your function when the app is ready
|
### Calling your function when the app is ready
|
||||||
|
|
||||||
```js title='main.js (Lines 12-14)'
|
```js title='main.js (Lines 12-14)' @ts-type={createWindow:()=>void}
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow()
|
createWindow()
|
||||||
})
|
})
|
||||||
|
@ -336,7 +336,7 @@ Because windows cannot be created before the `ready` event, you should only list
|
||||||
`activate` events after your app is initialized. Do this by only listening for activate
|
`activate` events after your app is initialized. Do this by only listening for activate
|
||||||
events inside your existing `whenReady()` callback.
|
events inside your existing `whenReady()` callback.
|
||||||
|
|
||||||
```js
|
```js @ts-type={createWindow:()=>void}
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow()
|
createWindow()
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ information in the window. This variable can be accessed via `window.versions` o
|
||||||
`versions`. Create a `renderer.js` script that uses the [`document.getElementById`][]
|
`versions`. Create a `renderer.js` script that uses the [`document.getElementById`][]
|
||||||
DOM API to replace the displayed text for the HTML element with `info` as its `id` property.
|
DOM API to replace the displayed text for the HTML element with `info` as its `id` property.
|
||||||
|
|
||||||
```js title="renderer.js"
|
```js title="renderer.js" @ts-nocheck
|
||||||
const information = document.getElementById('info')
|
const information = document.getElementById('info')
|
||||||
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
|
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
|
||||||
```
|
```
|
||||||
|
@ -225,7 +225,7 @@ app.whenReady().then(() => {
|
||||||
Once you have the sender and receiver set up, you can now send messages from the renderer
|
Once you have the sender and receiver set up, you can now send messages from the renderer
|
||||||
to the main process through the `'ping'` channel you just defined.
|
to the main process through the `'ping'` channel you just defined.
|
||||||
|
|
||||||
```js title='renderer.js'
|
```js title='renderer.js' @ts-expect-error=[2]
|
||||||
const func = async () => {
|
const func = async () => {
|
||||||
const response = await window.versions.ping()
|
const response = await window.versions.ping()
|
||||||
console.log(response) // prints out 'pong'
|
console.log(response) // prints out 'pong'
|
||||||
|
|
|
@ -188,7 +188,7 @@ npm install update-electron-app
|
||||||
|
|
||||||
Then, import the module and call it immediately in the main process.
|
Then, import the module and call it immediately in the main process.
|
||||||
|
|
||||||
```js title='main.js'
|
```js title='main.js' @ts-nocheck
|
||||||
require('update-electron-app')()
|
require('update-electron-app')()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ npm install update-electron-app
|
||||||
|
|
||||||
Then, invoke the updater from your app's main process file:
|
Then, invoke the updater from your app's main process file:
|
||||||
|
|
||||||
```js title="main.js"
|
```js title="main.js" @ts-nocheck
|
||||||
require('update-electron-app')()
|
require('update-electron-app')()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ Now that you've configured the basic update mechanism for your application, you
|
||||||
need to ensure that the user will get notified when there's an update. This
|
need to ensure that the user will get notified when there's an update. This
|
||||||
can be achieved using the [autoUpdater API events](../api/auto-updater.md#events):
|
can be achieved using the [autoUpdater API events](../api/auto-updater.md#events):
|
||||||
|
|
||||||
```javascript title="main.js"
|
```javascript title="main.js" @ts-expect-error=[11]
|
||||||
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
||||||
const dialogOpts = {
|
const dialogOpts = {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
|
|
|
@ -196,9 +196,9 @@ const win = new BrowserWindow({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('set-ignore-mouse-events', (event, ...args) => {
|
ipcMain.on('set-ignore-mouse-events', (event, ignore, options) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender)
|
const win = BrowserWindow.fromWebContents(event.sender)
|
||||||
win.setIgnoreMouseEvents(...args)
|
win.setIgnoreMouseEvents(ignore, options)
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ Starting with a working application from the
|
||||||
following lines:
|
following lines:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { BrowserWindow } = require('electron')
|
const { BrowserWindow, nativeImage } = require('electron')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
const win = new BrowserWindow()
|
const win = new BrowserWindow()
|
||||||
|
@ -133,11 +133,11 @@ const win = new BrowserWindow()
|
||||||
win.setThumbarButtons([
|
win.setThumbarButtons([
|
||||||
{
|
{
|
||||||
tooltip: 'button1',
|
tooltip: 'button1',
|
||||||
icon: path.join(__dirname, 'button1.png'),
|
icon: nativeImage.createFromPath(path.join(__dirname, 'button1.png')),
|
||||||
click () { console.log('button1 clicked') }
|
click () { console.log('button1 clicked') }
|
||||||
}, {
|
}, {
|
||||||
tooltip: 'button2',
|
tooltip: 'button2',
|
||||||
icon: path.join(__dirname, 'button2.png'),
|
icon: nativeImage.createFromPath(path.join(__dirname, 'button2.png')),
|
||||||
flags: ['enabled', 'dismissonclick'],
|
flags: ['enabled', 'dismissonclick'],
|
||||||
click () { console.log('button2 clicked.') }
|
click () { console.log('button2 clicked.') }
|
||||||
}
|
}
|
||||||
|
@ -189,11 +189,11 @@ Starting with a working application from the
|
||||||
following lines:
|
following lines:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { BrowserWindow } = require('electron')
|
const { BrowserWindow, nativeImage } = require('electron')
|
||||||
|
|
||||||
const win = new BrowserWindow()
|
const win = new BrowserWindow()
|
||||||
|
|
||||||
win.setOverlayIcon('path/to/overlay.png', 'Description for overlay')
|
win.setOverlayIcon(nativeImage.createFromPath('path/to/overlay.png'), 'Description for overlay')
|
||||||
```
|
```
|
||||||
|
|
||||||
[msdn-icon-overlay]: https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#icon-overlays
|
[msdn-icon-overlay]: https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#icon-overlays
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"@electron/docs-parser": "^1.1.0",
|
"@electron/docs-parser": "^1.1.0",
|
||||||
"@electron/fiddle-core": "^1.0.4",
|
"@electron/fiddle-core": "^1.0.4",
|
||||||
"@electron/github-app-auth": "^2.0.0",
|
"@electron/github-app-auth": "^2.0.0",
|
||||||
"@electron/lint-roller": "^1.2.1",
|
"@electron/lint-roller": "^1.5.0",
|
||||||
"@electron/typescript-definitions": "^8.14.0",
|
"@electron/typescript-definitions": "^8.14.0",
|
||||||
"@octokit/rest": "^19.0.7",
|
"@octokit/rest": "^19.0.7",
|
||||||
"@primer/octicons": "^10.0.0",
|
"@primer/octicons": "^10.0.0",
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
"@types/stream-json": "^1.5.1",
|
"@types/stream-json": "^1.5.1",
|
||||||
"@types/temp": "^0.8.34",
|
"@types/temp": "^0.8.34",
|
||||||
"@types/uuid": "^3.4.6",
|
"@types/uuid": "^3.4.6",
|
||||||
|
"@types/w3c-web-serial": "^1.0.3",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"@types/webpack-env": "^1.17.0",
|
"@types/webpack-env": "^1.17.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
||||||
|
@ -87,10 +88,11 @@
|
||||||
"lint:objc": "node ./script/lint.js --objc",
|
"lint:objc": "node ./script/lint.js --objc",
|
||||||
"lint:py": "node ./script/lint.js --py",
|
"lint:py": "node ./script/lint.js --py",
|
||||||
"lint:gn": "node ./script/lint.js --gn",
|
"lint:gn": "node ./script/lint.js --gn",
|
||||||
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdownlint",
|
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:ts-check-js-in-markdown && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdownlint",
|
||||||
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
|
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
|
||||||
"lint:docs-relative-links": "electron-lint-markdown-links --root docs \"**/*.md\"",
|
"lint:docs-relative-links": "electron-lint-markdown-links --root docs \"**/*.md\"",
|
||||||
"lint:markdownlint": "electron-markdownlint \"*.md\" \"docs/**/*.md\"",
|
"lint:markdownlint": "electron-markdownlint \"*.md\" \"docs/**/*.md\"",
|
||||||
|
"lint:ts-check-js-in-markdown": "electron-lint-markdown-ts-check --root docs \"**/*.md\" --ignore \"breaking-changes.md\"",
|
||||||
"lint:js-in-markdown": "electron-lint-markdown-standard --root docs \"**/*.md\"",
|
"lint:js-in-markdown": "electron-lint-markdown-standard --root docs \"**/*.md\"",
|
||||||
"create-api-json": "node script/create-api-json.js",
|
"create-api-json": "node script/create-api-json.js",
|
||||||
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
|
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
|
||||||
|
|
58
yarn.lock
58
yarn.lock
|
@ -194,10 +194,10 @@
|
||||||
"@octokit/auth-app" "^4.0.13"
|
"@octokit/auth-app" "^4.0.13"
|
||||||
"@octokit/rest" "^19.0.11"
|
"@octokit/rest" "^19.0.11"
|
||||||
|
|
||||||
"@electron/lint-roller@^1.2.1":
|
"@electron/lint-roller@^1.5.0":
|
||||||
version "1.2.1"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@electron/lint-roller/-/lint-roller-1.2.1.tgz#9f9d99b0a8975646e0a0131ab1b21a2ec62e80d8"
|
resolved "https://registry.yarnpkg.com/@electron/lint-roller/-/lint-roller-1.5.0.tgz#9b743979e1b03327e475fa696bb781eb2ea05ef2"
|
||||||
integrity sha512-w9PelpTBX8ClAv2iVa8fYqK77dnN0zWiHW98Utf8D83nmxkCMQNrKdRupSyiuIttbic1Nao8FhTScppmzOz0gw==
|
integrity sha512-205UxwJEx8zv5wLwPq4wMA0OYrJ7d1GuqOhPav0Uy2HWe4K+DZbSP50safCvZCSpI6Op3DMo79tp5i8VppuPWA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@dsanders11/vscode-markdown-languageservice" "^0.3.0"
|
"@dsanders11/vscode-markdown-languageservice" "^0.3.0"
|
||||||
glob "^8.1.0"
|
glob "^8.1.0"
|
||||||
|
@ -206,6 +206,7 @@
|
||||||
mdast-util-from-markdown "^1.3.0"
|
mdast-util-from-markdown "^1.3.0"
|
||||||
minimist "^1.2.8"
|
minimist "^1.2.8"
|
||||||
node-fetch "^2.6.9"
|
node-fetch "^2.6.9"
|
||||||
|
rimraf "^4.4.1"
|
||||||
standard "^17.0.0"
|
standard "^17.0.0"
|
||||||
unist-util-visit "^4.1.2"
|
unist-util-visit "^4.1.2"
|
||||||
vscode-languageserver "^8.1.0"
|
vscode-languageserver "^8.1.0"
|
||||||
|
@ -1066,6 +1067,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/w3c-web-serial@^1.0.3":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/w3c-web-serial/-/w3c-web-serial-1.0.3.tgz#9fd5e8542f74e464bb1715b384b5c0dcbf2fb2c3"
|
||||||
|
integrity sha512-R4J/OjqKAUFQoXVIkaUTfzb/sl6hLh/ZhDTfowJTRMa7LhgEmI/jXV4zsL1u8HpNa853BxwNmDIr0pauizzwSQ==
|
||||||
|
|
||||||
"@types/webpack-env@^1.17.0":
|
"@types/webpack-env@^1.17.0":
|
||||||
version "1.17.0"
|
version "1.17.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.17.0.tgz#f99ce359f1bfd87da90cc4a57cab0a18f34a48d0"
|
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.17.0.tgz#f99ce359f1bfd87da90cc4a57cab0a18f34a48d0"
|
||||||
|
@ -3156,6 +3162,16 @@ glob@^8.1.0:
|
||||||
minimatch "^5.0.1"
|
minimatch "^5.0.1"
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
|
|
||||||
|
glob@^9.2.0:
|
||||||
|
version "9.3.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21"
|
||||||
|
integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
minimatch "^8.0.2"
|
||||||
|
minipass "^4.2.4"
|
||||||
|
path-scurry "^1.6.1"
|
||||||
|
|
||||||
glob@~8.0.3:
|
glob@~8.0.3:
|
||||||
version "8.0.3"
|
version "8.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
|
||||||
|
@ -4078,7 +4094,7 @@ lru-cache@^6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
lru-cache@^9.0.0:
|
lru-cache@^9.0.0, lru-cache@^9.1.1:
|
||||||
version "9.1.1"
|
version "9.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.1.1.tgz#c58a93de58630b688de39ad04ef02ef26f1902f1"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.1.1.tgz#c58a93de58630b688de39ad04ef02ef26f1902f1"
|
||||||
integrity sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==
|
integrity sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==
|
||||||
|
@ -4514,6 +4530,13 @@ minimatch@^5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^2.0.1"
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
|
minimatch@^8.0.2:
|
||||||
|
version "8.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229"
|
||||||
|
integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
minimatch@~5.1.2:
|
minimatch@~5.1.2:
|
||||||
version "5.1.2"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff"
|
||||||
|
@ -4543,6 +4566,16 @@ minipass@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.1.tgz#2b9408c6e81bb8b338d600fb3685e375a370a057"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.1.tgz#2b9408c6e81bb8b338d600fb3685e375a370a057"
|
||||||
integrity sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==
|
integrity sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==
|
||||||
|
|
||||||
|
minipass@^4.2.4:
|
||||||
|
version "4.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a"
|
||||||
|
integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==
|
||||||
|
|
||||||
|
"minipass@^5.0.0 || ^6.0.2":
|
||||||
|
version "6.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81"
|
||||||
|
integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==
|
||||||
|
|
||||||
minizlib@^2.1.1:
|
minizlib@^2.1.1:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||||
|
@ -4933,6 +4966,14 @@ path-parse@^1.0.6, path-parse@^1.0.7:
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
|
path-scurry@^1.6.1:
|
||||||
|
version "1.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.9.2.tgz#90f9d296ac5e37e608028e28a447b11d385b3f63"
|
||||||
|
integrity sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^9.1.1"
|
||||||
|
minipass "^5.0.0 || ^6.0.2"
|
||||||
|
|
||||||
path-to-regexp@0.1.7:
|
path-to-regexp@0.1.7:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
|
@ -5830,6 +5871,13 @@ rimraf@^3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
|
rimraf@^4.4.1:
|
||||||
|
version "4.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755"
|
||||||
|
integrity sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==
|
||||||
|
dependencies:
|
||||||
|
glob "^9.2.0"
|
||||||
|
|
||||||
rimraf@~2.2.6:
|
rimraf@~2.2.6:
|
||||||
version "2.2.8"
|
version "2.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue