From 0d70389ccb1c9364e424efa2eb06352f0f05aa8a Mon Sep 17 00:00:00 2001 From: David Sanders Date: Thu, 29 May 2025 12:45:26 -0700 Subject: [PATCH] chore: lint code blocks in docs with ESLint (#42113) --- docs/.eslintrc.json | 35 +++++++ docs/api/app.md | 6 ++ docs/api/base-window.md | 4 + docs/api/browser-window.md | 8 +- docs/api/command-line-switches.md | 2 + docs/api/command-line.md | 1 + docs/api/context-bridge.md | 2 + docs/api/debugger.md | 1 + docs/api/dialog.md | 5 + docs/api/dock.md | 1 + docs/api/download-item.md | 1 + docs/api/extensions-api.md | 1 + docs/api/message-channel-main.md | 4 + docs/api/native-image.md | 1 + docs/api/net.md | 1 + docs/api/protocol.md | 11 ++- docs/api/service-workers.md | 1 + docs/api/session.md | 13 ++- docs/api/structures/printer-info.md | 2 + docs/api/structures/trace-config.md | 2 + docs/api/system-preferences.md | 1 + docs/api/view.md | 1 + docs/api/web-contents-view.md | 2 + docs/api/web-contents.md | 9 +- docs/api/web-frame.md | 7 +- docs/api/web-utils.md | 1 + docs/api/webview-tag.md | 1 + docs/development/creating-api.md | 4 +- docs/faq.md | 4 + docs/tutorial/asar-archives.md | 5 + docs/tutorial/automated-testing.md | 9 +- docs/tutorial/custom-title-bar.md | 5 + docs/tutorial/custom-window-interactions.md | 2 + docs/tutorial/dark-mode.md | 1 + docs/tutorial/devtools-extension.md | 7 +- docs/tutorial/esm.md | 2 + docs/tutorial/in-app-purchases.md | 1 + docs/tutorial/ipc.md | 6 ++ .../launch-app-from-url-in-another-app.md | 1 + docs/tutorial/message-ports.md | 1 + .../native-code-and-electron-objc-macos.md | 2 +- docs/tutorial/native-code-and-electron.md | 5 +- docs/tutorial/navigation-history.md | 1 - docs/tutorial/performance.md | 1 + docs/tutorial/process-model.md | 2 +- docs/tutorial/security.md | 8 +- docs/tutorial/tutorial-3-preload.md | 2 + docs/tutorial/windows-taskbar.md | 1 + package.json | 1 + script/lint.js | 54 ++++++++--- yarn.lock | 93 +++++++++++++++++++ 51 files changed, 308 insertions(+), 34 deletions(-) create mode 100644 docs/.eslintrc.json diff --git a/docs/.eslintrc.json b/docs/.eslintrc.json new file mode 100644 index 0000000000..ee6dda4b04 --- /dev/null +++ b/docs/.eslintrc.json @@ -0,0 +1,35 @@ +{ + "extends": "standard", + "plugins": [ + "markdown", + "unicorn" + ], + "overrides": [ + { + "files": ["*.md", "**/*.md"], + "processor": "markdown/markdown" + } + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off", + "import/order": ["error", { + "alphabetize": { + "order": "asc" + }, + "newlines-between": "always", + "pathGroups": [ + { + "pattern": "{electron,electron/**}", + "group": "builtin", + "position": "before" + } + ], + "pathGroupsExcludedImportTypes": [] + }], + "n/no-callback-literal": "off", + "no-undef": "off", + "no-unused-expressions": "off", + "no-unused-vars": "off", + "unicorn/prefer-node-protocol": "error" + } +} diff --git a/docs/api/app.md b/docs/api/app.md index 119c867abe..0ed350dad7 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -9,6 +9,7 @@ closed: ```js const { app } = require('electron') + app.on('window-all-closed', () => { app.quit() }) @@ -1023,6 +1024,7 @@ starts: ```js const { app, BrowserWindow } = require('electron') + let myWindow = null const additionalData = { myKey: 'myValue' } @@ -1226,6 +1228,8 @@ For `infoType` equal to `complete`: For `infoType` equal to `basic`: Promise is fulfilled with `Object` containing fewer attributes than when requested with `complete`. Here's an example of basic response: + + ```js { auxAttributes: @@ -1339,6 +1343,7 @@ latest version. ``` js const { app } = require('electron') + const path = require('node:path') const appFolder = path.dirname(process.execPath) @@ -1413,6 +1418,7 @@ Returns `Function` - This function **must** be called once you have finished acc ```js const { app, dialog } = require('electron') + const fs = require('node:fs') let filepath diff --git a/docs/api/base-window.md b/docs/api/base-window.md index 52e6deb288..5da103dc32 100644 --- a/docs/api/base-window.md +++ b/docs/api/base-window.md @@ -294,6 +294,7 @@ e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`. ```js const { BaseWindow } = require('electron') + const win = new BaseWindow() win.on('app-command', (e, cmd) => { // Navigate the window back when the user hits their mouse back button @@ -502,6 +503,7 @@ A `boolean` property that determines whether the window is excluded from the app ```js @ts-expect-error=[12] const { Menu, BaseWindow } = require('electron') + const win = new BaseWindow({ height: 600, width: 600 }) const template = [ @@ -727,6 +729,7 @@ Resizes and moves the window to the supplied bounds. Any properties that are not ```js const { BaseWindow } = require('electron') + const win = new BaseWindow() // set all bounds properties @@ -987,6 +990,7 @@ a HTML-rendered toolbar. For example: ```js const { BaseWindow } = require('electron') + const win = new BaseWindow() const toolbarRect = document.getElementById('toolbar').getBoundingClientRect() diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index e61faa458f..0d575d688b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -40,6 +40,7 @@ the window after this event will have no visual flash: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ show: false }) win.once('ready-to-show', () => { win.show() @@ -373,6 +374,7 @@ e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.on('app-command', (e, cmd) => { // Navigate the window back when the user hits their mouse back button @@ -820,6 +822,7 @@ Resizes and moves the window to the supplied bounds. Any properties that are not ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() // set all bounds properties @@ -1080,6 +1083,7 @@ a HTML-rendered toolbar. For example: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() const toolbarRect = document.getElementById('toolbar').getBoundingClientRect() @@ -1232,9 +1236,10 @@ method: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() -const url = require('url').format({ +const url = require('node:url').format({ protocol: 'file', slashes: true, pathname: require('node:path').join(__dirname, 'index.html') @@ -1248,6 +1253,7 @@ the following: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.loadURL('http://localhost:8000/post', { diff --git a/docs/api/command-line-switches.md b/docs/api/command-line-switches.md index 8026d9351d..8a55552097 100644 --- a/docs/api/command-line-switches.md +++ b/docs/api/command-line-switches.md @@ -8,6 +8,7 @@ is emitted: ```js const { app } = require('electron') + app.commandLine.appendSwitch('remote-debugging-port', '8315') app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1') @@ -188,6 +189,7 @@ For example: ```js const { app } = require('electron') + app.commandLine.appendSwitch('proxy-bypass-list', ';*.google.com;*foo.com;1.2.3.4:5678') ``` diff --git a/docs/api/command-line.md b/docs/api/command-line.md index 373bee8417..e424ba1f1c 100644 --- a/docs/api/command-line.md +++ b/docs/api/command-line.md @@ -9,6 +9,7 @@ The following example shows how to check if the `--disable-gpu` flag is set. ```js const { app } = require('electron') + app.commandLine.hasSwitch('disable-gpu') ``` diff --git a/docs/api/context-bridge.md b/docs/api/context-bridge.md index 1776b7c61a..4c63e411ef 100644 --- a/docs/api/context-bridge.md +++ b/docs/api/context-bridge.md @@ -189,7 +189,9 @@ Be very cautious about which globals and APIs you expose to untrusted remote con ```js const { contextBridge } = require('electron') + const crypto = require('node:crypto') + contextBridge.exposeInMainWorld('nodeCrypto', { sha256sum (data) { const hash = crypto.createHash('sha256') diff --git a/docs/api/debugger.md b/docs/api/debugger.md index 26a4b7c6a9..ddbbfa1d04 100644 --- a/docs/api/debugger.md +++ b/docs/api/debugger.md @@ -10,6 +10,7 @@ runtime that allows interacting with pages and instrumenting them. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() try { diff --git a/docs/api/dialog.md b/docs/api/dialog.md index e1c641c724..684a9b66b6 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -8,6 +8,7 @@ An example of showing a dialog to select multiple files: ```js const { dialog } = require('electron') + console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })) ``` @@ -52,6 +53,8 @@ The `window` argument allows the dialog to attach itself to a parent window, mak The `filters` specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example: + + ```js { filters: [ @@ -126,6 +129,8 @@ The `window` argument allows the dialog to attach itself to a parent window, mak The `filters` specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example: + + ```js { filters: [ diff --git a/docs/api/dock.md b/docs/api/dock.md index 6bac22e9b9..691e6c8842 100644 --- a/docs/api/dock.md +++ b/docs/api/dock.md @@ -9,6 +9,7 @@ The following example shows how to bounce your icon on the dock. ```js const { app } = require('electron') + app.dock?.bounce() ``` diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 06d52a44ea..253c722f09 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -12,6 +12,7 @@ control the download item. ```js // In the main process. const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.webContents.session.on('will-download', (event, item, webContents) => { // Set the save path, making Electron not to prompt a save dialog. diff --git a/docs/api/extensions-api.md b/docs/api/extensions-api.md index afbb40574e..31999b0526 100644 --- a/docs/api/extensions-api.md +++ b/docs/api/extensions-api.md @@ -77,6 +77,7 @@ extension to be loaded. ```js const { app, session } = require('electron') + const path = require('node:path') app.whenReady().then(async () => { diff --git a/docs/api/message-channel-main.md b/docs/api/message-channel-main.md index 18339848db..39c8b6cfce 100644 --- a/docs/api/message-channel-main.md +++ b/docs/api/message-channel-main.md @@ -15,9 +15,12 @@ Process: [Main](../glossary.md#main-process) Example: + + ```js // Main process const { BrowserWindow, MessageChannelMain } = require('electron') + const w = new BrowserWindow() const { port1, port2 } = new MessageChannelMain() w.webContents.postMessage('port', null, [port2]) @@ -25,6 +28,7 @@ port1.postMessage({ some: 'message' }) // Renderer process const { ipcRenderer } = require('electron') + ipcRenderer.on('port', (e) => { // e.ports is a list of ports sent along with this message e.ports[0].onmessage = (messageEvent) => { diff --git a/docs/api/native-image.md b/docs/api/native-image.md index a867cfca5e..68ecbbe1ad 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -86,6 +86,7 @@ images/ ```js title='Main Process' const { Tray } = require('electron') + const appTray = new Tray('/Users/somebody/images/icon.png') ``` diff --git a/docs/api/net.md b/docs/api/net.md index 2b42e445ff..7f166b7521 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -28,6 +28,7 @@ Example usage: ```js const { app } = require('electron') + app.whenReady().then(() => { const { net } = require('electron') const request = net.request('https://github.com') diff --git a/docs/api/protocol.md b/docs/api/protocol.md index a14cd01b62..e8d5a22a2f 100644 --- a/docs/api/protocol.md +++ b/docs/api/protocol.md @@ -9,6 +9,7 @@ An example of implementing a protocol that has the same effect as the ```js const { app, protocol, net } = require('electron') + const path = require('node:path') const url = require('node:url') @@ -38,8 +39,9 @@ to register it to that session explicitly. ```js const { app, BrowserWindow, net, protocol, session } = require('electron') + const path = require('node:path') -const url = require('url') +const url = require('node:url') app.whenReady().then(() => { const partition = 'persist:example' @@ -76,6 +78,7 @@ Policy: ```js const { protocol } = require('electron') + protocol.registerSchemesAsPrivileged([ { scheme: 'foo', privileges: { bypassCSP: true } } ]) @@ -128,8 +131,9 @@ Example: ```js const { app, net, protocol } = require('electron') + const path = require('node:path') -const { pathToFileURL } = require('url') +const { pathToFileURL } = require('node:url') protocol.registerSchemesAsPrivileged([ { @@ -330,7 +334,8 @@ Example: ```js const { protocol } = require('electron') -const { PassThrough } = require('stream') + +const { PassThrough } = require('node:stream') function createStream (text) { const rv = new PassThrough() // PassThrough is also a Readable stream diff --git a/docs/api/service-workers.md b/docs/api/service-workers.md index e8a843cca6..2132368b80 100644 --- a/docs/api/service-workers.md +++ b/docs/api/service-workers.md @@ -109,6 +109,7 @@ Starts the service worker or does nothing if already running. ```js const { app, session } = require('electron') + const { serviceWorkers } = session.defaultSession // Collect service workers scopes diff --git a/docs/api/session.md b/docs/api/session.md index 105dfb5f76..1d13094426 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -79,6 +79,7 @@ You can create a `Session` object in the `session` module: ```js const { session } = require('electron') + const ses = session.fromPartition('persist:name') console.log(ses.getUserAgent()) ``` @@ -100,8 +101,9 @@ Emitted when Electron is about to download `item` in `webContents`. Calling `event.preventDefault()` will cancel the download and `item` will not be available from next tick of the process. -```js @ts-expect-error=[4] +```js @ts-expect-error=[5] const { session } = require('electron') + session.defaultSession.on('will-download', (event, item, webContents) => { event.preventDefault() require('got')(item.getURL()).then((response) => { @@ -852,6 +854,7 @@ verify proc. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.webContents.session.setCertificateVerifyProc((request, callback) => { @@ -903,6 +906,7 @@ Most web APIs do a permission check and then make a permission request if the ch ```js const { session } = require('electron') + session.fromPartition('some-partition').setPermissionRequestHandler((webContents, permission, callback) => { if (webContents.getURL() === 'some-host' && permission === 'notifications') { return callback(false) // denied. @@ -952,7 +956,9 @@ To clear the handler, call `setPermissionCheckHandler(null)`. ```js const { session } = require('electron') -const url = require('url') + +const url = require('node:url') + session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission, requestingOrigin) => { if (new URL(requestingOrigin).hostname === 'some-host' && permission === 'notifications') { return true // granted @@ -1189,6 +1195,7 @@ automatically. To clear the handler, call `setBluetoothPairingHandler(null)`. ```js const { app, BrowserWindow, session } = require('electron') + const path = require('node:path') function createWindow () { @@ -1518,6 +1525,7 @@ extension to be loaded. ```js const { app, session } = require('electron') + const path = require('node:path') app.whenReady().then(async () => { @@ -1659,6 +1667,7 @@ A [`Protocol`](protocol.md) object for this session. ```js const { app, session } = require('electron') + const path = require('node:path') app.whenReady().then(() => { diff --git a/docs/api/structures/printer-info.md b/docs/api/structures/printer-info.md index 6ca9f12d64..958d99993c 100644 --- a/docs/api/structures/printer-info.md +++ b/docs/api/structures/printer-info.md @@ -12,6 +12,8 @@ The number represented by `status` means different things on different platforms Below is an example of some of the additional options that may be set which may be different on each platform. + + ```js { name: 'Austin_4th_Floor_Printer___C02XK13BJHD4', diff --git a/docs/api/structures/trace-config.md b/docs/api/structures/trace-config.md index 2f33aec0a0..d63ed37d31 100644 --- a/docs/api/structures/trace-config.md +++ b/docs/api/structures/trace-config.md @@ -26,6 +26,8 @@ An example TraceConfig that roughly matches what Chrome DevTools records: + + ```js { recording_mode: 'record-until-full', diff --git a/docs/api/system-preferences.md b/docs/api/system-preferences.md index 3a6488274e..8af85f757d 100644 --- a/docs/api/system-preferences.md +++ b/docs/api/system-preferences.md @@ -6,6 +6,7 @@ Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-p ```js const { systemPreferences } = require('electron') + console.log(systemPreferences.getEffectiveAppearance()) ``` diff --git a/docs/api/view.md b/docs/api/view.md index 8e0a23a5d8..2eb7f0a4b4 100644 --- a/docs/api/view.md +++ b/docs/api/view.md @@ -9,6 +9,7 @@ module is emitted. ```js const { BaseWindow, View } = require('electron') + const win = new BaseWindow() const view = new View() diff --git a/docs/api/web-contents-view.md b/docs/api/web-contents-view.md index 66bb257cf0..1ab79632fc 100644 --- a/docs/api/web-contents-view.md +++ b/docs/api/web-contents-view.md @@ -9,6 +9,7 @@ module is emitted. ```js const { BaseWindow, WebContentsView } = require('electron') + const win = new BaseWindow({ width: 800, height: 400 }) const view1 = new WebContentsView() @@ -52,6 +53,7 @@ Use this to interact with the `WebContents`, for instance to load a URL. ```js const { WebContentsView } = require('electron') + const view = new WebContentsView() view.webContents.loadURL('https://electronjs.org/') ``` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 3e89f5e6f7..2b5249c337 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -55,6 +55,7 @@ These methods can be accessed from the `webContents` module: ```js const { webContents } = require('electron') + console.log(webContents) ``` @@ -446,6 +447,7 @@ and allow the page to be unloaded. ```js const { BrowserWindow, dialog } = require('electron') + const win = new BrowserWindow({ width: 800, height: 600 }) win.webContents.on('will-prevent-unload', (event) => { const choice = dialog.showMessageBoxSync(win, { @@ -1103,6 +1105,7 @@ Returns `string` - The URL of the current web page. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ width: 800, height: 600 }) win.loadURL('https://github.com').then(() => { const currentURL = win.webContents.getURL() @@ -1772,9 +1775,10 @@ An example of `webContents.printToPDF`: ```js const { app, BrowserWindow } = require('electron') + const fs = require('node:fs') -const path = require('node:path') const os = require('node:os') +const path = require('node:path') app.whenReady().then(() => { const win = new BrowserWindow() @@ -1806,6 +1810,7 @@ creation: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.webContents.on('devtools-opened', () => { win.webContents.addWorkSpace(__dirname) @@ -1872,6 +1877,7 @@ An example of showing devtools in a `` tag: ```js // Main process const { ipcMain, webContents } = require('electron') + ipcMain.on('open-devtools', (event, targetContentsId, devtoolsContentsId) => { const target = webContents.fromId(targetContentsId) const devtools = webContents.fromId(devtoolsContentsId) @@ -2131,6 +2137,7 @@ Returns `Promise` - resolves if the page is saved. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.loadURL('https://github.com') diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 301c002bd1..98e5954885 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -99,9 +99,11 @@ with an array of misspelt words when complete. An example of using [node-spellchecker][spellchecker] as provider: -```js @ts-expect-error=[2,6] +```js @ts-expect-error=[3,8] const { webFrame } = require('electron') + const spellChecker = require('spellchecker') + webFrame.setSpellCheckProvider('en-US', { spellCheck (words, callback) { setTimeout(() => { @@ -212,11 +214,14 @@ caches. ```js const { webFrame } = require('electron') + console.log(webFrame.getResourceUsage()) ``` This will generate: + + ```js { images: { diff --git a/docs/api/web-utils.md b/docs/api/web-utils.md index 54ff8c03ab..6ce407260e 100644 --- a/docs/api/web-utils.md +++ b/docs/api/web-utils.md @@ -22,5 +22,6 @@ const oldPath = document.querySelector('input').files[0].path // After const { webUtils } = require('electron') + const newPath = webUtils.getPathForFile(document.querySelector('input').files[0]) ``` diff --git a/docs/api/webview-tag.md b/docs/api/webview-tag.md index 385358728a..9be3e881a3 100644 --- a/docs/api/webview-tag.md +++ b/docs/api/webview-tag.md @@ -987,6 +987,7 @@ webview.send('ping') ```js // In guest page. const { ipcRenderer } = require('electron') + ipcRenderer.on('ping', () => { ipcRenderer.sendToHost('pong') }) diff --git a/docs/development/creating-api.md b/docs/development/creating-api.md index 49f383f33f..ca237704f3 100644 --- a/docs/development/creating-api.md +++ b/docs/development/creating-api.md @@ -165,8 +165,10 @@ An example of the contents of this file can be found [here](https://github.com/e Add your module to the module list found at `"lib/browser/api/module-list.ts"` like so: + + ```ts title='lib/browser/api/module-list.ts' @ts-nocheck export const browserModuleList: ElectronInternal.ModuleEntry[] = [ - { name: 'apiName', loader: () => require('./api-name') }, + { name: 'apiName', loader: () => require('./api-name') } ]; ``` diff --git a/docs/faq.md b/docs/faq.md index 114731d69d..22969c542b 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -67,6 +67,7 @@ code from this: ```js const { app, Tray } = require('electron') + app.whenReady().then(() => { const tray = new Tray('/path/to/icon.png') tray.setTitle('hello world') @@ -77,6 +78,7 @@ to this: ```js const { app, Tray } = require('electron') + let tray = null app.whenReady().then(() => { tray = new Tray('/path/to/icon.png') @@ -95,6 +97,7 @@ To solve this, you can turn off node integration in Electron: ```js // In the main process. const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ webPreferences: { nodeIntegration: false @@ -143,6 +146,7 @@ To achieve this goal, set the background in the constructor for [BrowserWindow][ ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ backgroundColor: '#fff' }) diff --git a/docs/tutorial/asar-archives.md b/docs/tutorial/asar-archives.md index 7752d8fbe2..0474d8d871 100644 --- a/docs/tutorial/asar-archives.md +++ b/docs/tutorial/asar-archives.md @@ -42,6 +42,7 @@ Read a file in the ASAR archive: ```js const fs = require('node:fs') + fs.readFileSync('/path/to/example.asar/file.txt') ``` @@ -49,6 +50,7 @@ List all files under the root of the archive: ```js const fs = require('node:fs') + fs.readdirSync('/path/to/example.asar') ``` @@ -62,6 +64,7 @@ You can also display a web page in an ASAR archive with `BrowserWindow`: ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.loadURL('file:///path/to/example.asar/static/index.html') @@ -91,6 +94,7 @@ content of an ASAR archive as a file. For this purpose you can use the built-in ```js const originalFs = require('original-fs') + originalFs.readFileSync('/path/to/example.asar') ``` @@ -99,6 +103,7 @@ the `fs` module: ```js const fs = require('node:fs') + process.noAsar = true fs.readFileSync('/path/to/example.asar') ``` diff --git a/docs/tutorial/automated-testing.md b/docs/tutorial/automated-testing.md index d2c565278c..34f3c3606c 100644 --- a/docs/tutorial/automated-testing.md +++ b/docs/tutorial/automated-testing.md @@ -95,6 +95,7 @@ or to retrieve other Electron process information: ```js @ts-nocheck import fs from 'node:fs' import path from 'node:path' + import { browser, expect } from '@wdio/globals' const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), { encoding: 'utf-8' })) @@ -165,6 +166,7 @@ ChromeDriver and where to find the binary of your Electron app: ```js title='test.js' @ts-expect-error=[1] const webdriver = require('selenium-webdriver') + const driver = new webdriver.Builder() // The "9515" is the port opened by ChromeDriver. .usingServer('http://localhost:9515') @@ -317,9 +319,10 @@ To create a custom driver, we'll use Node.js' [`child_process`](https://nodejs.o The test suite will spawn the Electron process, then establish a simple messaging protocol: ```js title='testDriver.js' @ts-nocheck -const childProcess = require('node:child_process') const electronPath = require('electron') +const childProcess = require('node:child_process') + // spawn the process const env = { /* ... */ } const stdio = ['inherit', 'inherit', 'inherit', 'ipc'] @@ -436,8 +439,10 @@ framework of your choosing. The following example uses or Mocha would work as well: ```js title='test.js' @ts-nocheck -const test = require('ava') const electronPath = require('electron') + +const test = require('ava') + const { TestDriver } = require('./testDriver') const app = new TestDriver({ diff --git a/docs/tutorial/custom-title-bar.md b/docs/tutorial/custom-title-bar.md index eb22162cf5..5c2b2a8144 100644 --- a/docs/tutorial/custom-title-bar.md +++ b/docs/tutorial/custom-title-bar.md @@ -76,6 +76,7 @@ use the native UI to control the window. ```js const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover' }) ``` @@ -89,6 +90,7 @@ by a fixed amount. ```js title='main.js' const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' }) ``` @@ -98,6 +100,7 @@ constructor. ```js title='main.js' const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ titleBarStyle: 'hidden', trafficLightPosition: { x: 10, y: 10 } @@ -112,6 +115,7 @@ on the value of its boolean parameter. ```js title='main.js' const { BrowserWindow } = require('electron') + const win = new BrowserWindow() // hides the traffic lights win.setWindowButtonVisibility(false) @@ -149,6 +153,7 @@ default to the standard system height: ```js title='main.js' const { BrowserWindow } = require('electron') + const win = new BrowserWindow({ titleBarStyle: 'hidden', titleBarOverlay: { diff --git a/docs/tutorial/custom-window-interactions.md b/docs/tutorial/custom-window-interactions.md index 6801594b94..7565ecaa73 100644 --- a/docs/tutorial/custom-window-interactions.md +++ b/docs/tutorial/custom-window-interactions.md @@ -62,6 +62,7 @@ API: ```js title='main.js' const { BrowserWindow } = require('electron') + const win = new BrowserWindow() win.setIgnoreMouseEvents(true) ``` @@ -75,6 +76,7 @@ allowing events such as `mouseleave` to be emitted: ```js title='main.js' const { BrowserWindow, ipcMain } = require('electron') + const path = require('node:path') const win = new BrowserWindow({ diff --git a/docs/tutorial/dark-mode.md b/docs/tutorial/dark-mode.md index d069ed8b5d..6ed30beafa 100644 --- a/docs/tutorial/dark-mode.md +++ b/docs/tutorial/dark-mode.md @@ -135,6 +135,7 @@ Finally, the `main.js` file represents the main process and contains the actual ```js const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron') + const path = require('node:path') const createWindow = () => { diff --git a/docs/tutorial/devtools-extension.md b/docs/tutorial/devtools-extension.md index dbd2796bca..679e3e749a 100644 --- a/docs/tutorial/devtools-extension.md +++ b/docs/tutorial/devtools-extension.md @@ -35,15 +35,16 @@ Using the [React Developer Tools][react-devtools] as an example: ```js const { app, session } = require('electron') - const path = require('node:path') + const os = require('node:os') - + const path = require('node:path') + // on macOS const reactDevToolsPath = path.join( os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0' ) - + app.whenReady().then(async () => { await session.defaultSession.loadExtension(reactDevToolsPath) }) diff --git a/docs/tutorial/esm.md b/docs/tutorial/esm.md index dc2aad5687..ae532fbba5 100644 --- a/docs/tutorial/esm.md +++ b/docs/tutorial/esm.md @@ -85,6 +85,8 @@ The `@babel/plugin-transform-modules-commonjs` plugin will transform ESM imports down to `require` calls. The exact syntax will depend on the [`importInterop` setting](https://babeljs.io/docs/babel-plugin-transform-modules-commonjs#importinterop). + + ```js @nolint @ts-nocheck title='@babel/plugin-transform-modules-commonjs' import foo from "foo"; import { bar } from "bar"; diff --git a/docs/tutorial/in-app-purchases.md b/docs/tutorial/in-app-purchases.md index d5f9479f4d..0696bf260a 100644 --- a/docs/tutorial/in-app-purchases.md +++ b/docs/tutorial/in-app-purchases.md @@ -37,6 +37,7 @@ Here is an example that shows how to use In-App Purchases in Electron. You'll ha ```js // Main process const { inAppPurchase } = require('electron') + const PRODUCT_IDS = ['id1', 'id2'] // Listen for transactions as soon as possible. diff --git a/docs/tutorial/ipc.md b/docs/tutorial/ipc.md index b8b0bad421..00d21ff341 100644 --- a/docs/tutorial/ipc.md +++ b/docs/tutorial/ipc.md @@ -52,6 +52,7 @@ In the main process, set an IPC listener on the `set-title` channel with the `ip ```js {6-10,22} title='main.js (Main Process)' const { app, BrowserWindow, ipcMain } = require('electron') + const path = require('node:path') // ... @@ -183,6 +184,7 @@ provided to the renderer process. Please refer to ```js {6-13,25} title='main.js (Main Process)' const { app, BrowserWindow, dialog, ipcMain } = require('electron') + const path = require('node:path') // ... @@ -334,6 +336,7 @@ response. ```js title='main.js (Main Process)' const { ipcMain } = require('electron') + ipcMain.on('synchronous-message', (event, arg) => { console.log(arg) // prints "ping" in the Node console event.returnValue = 'pong' @@ -378,6 +381,7 @@ target renderer. ```js {11-26} title='main.js (Main Process)' const { app, BrowserWindow, Menu, ipcMain } = require('electron') + const path = require('node:path') function createWindow () { @@ -412,6 +416,8 @@ function createWindow () { 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. + + ```js @ts-type={mainWindow:Electron.BrowserWindow} click: () => mainWindow.webContents.send('update-counter', -1) ``` diff --git a/docs/tutorial/launch-app-from-url-in-another-app.md b/docs/tutorial/launch-app-from-url-in-another-app.md index 6a49f20d6d..8e1c994c9b 100644 --- a/docs/tutorial/launch-app-from-url-in-another-app.md +++ b/docs/tutorial/launch-app-from-url-in-another-app.md @@ -27,6 +27,7 @@ control our application lifecycle and create a native browser window. ```js const { app, BrowserWindow, shell } = require('electron') + const path = require('node:path') ``` diff --git a/docs/tutorial/message-ports.md b/docs/tutorial/message-ports.md index 90703a4ccd..37c48fad9a 100644 --- a/docs/tutorial/message-ports.md +++ b/docs/tutorial/message-ports.md @@ -303,6 +303,7 @@ without having to step through the isolated world. ```js title='main.js (Main Process)' const { BrowserWindow, app, MessageChannelMain } = require('electron') + const path = require('node:path') app.whenReady().then(async () => { diff --git a/docs/tutorial/native-code-and-electron-objc-macos.md b/docs/tutorial/native-code-and-electron-objc-macos.md index 7074acda10..5572a05bf6 100644 --- a/docs/tutorial/native-code-and-electron-objc-macos.md +++ b/docs/tutorial/native-code-and-electron-objc-macos.md @@ -1075,7 +1075,7 @@ NODE_API_MODULE(objc_addon, Init) You're so close! We now have working Objective-C and thread-safe ways to expose methods and events to JavaScript. In this final step, let's create a JavaScript wrapper in `js/index.js` to provide a more friendly API: ```js title='js/index.js' @ts-expect-error=[10] -const EventEmitter = require('events') +const EventEmitter = require('node:events') class ObjcMacosAddon extends EventEmitter { constructor () { diff --git a/docs/tutorial/native-code-and-electron.md b/docs/tutorial/native-code-and-electron.md index 70ca945db4..c447ecdb31 100644 --- a/docs/tutorial/native-code-and-electron.md +++ b/docs/tutorial/native-code-and-electron.md @@ -269,8 +269,10 @@ Let's break down this code: Now, let's create a JavaScript wrapper to make the addon easier to use. Create `js/index.js`: + + ```js title='js/index.js' @ts-expect-error=[5] -const EventEmitter = require('events') +const EventEmitter = require('node:events') // Load the native addon using the 'bindings' module // This will look for the compiled .node file in various places @@ -362,6 +364,7 @@ To use this addon in an Electron application, you would: ```js @ts-expect-error=[2] // In your main process const myAddon = require('my-native-addon') + console.log(myAddon.helloWorld('Electron')) ``` diff --git a/docs/tutorial/navigation-history.md b/docs/tutorial/navigation-history.md index 807d3b676b..5460f945a6 100644 --- a/docs/tutorial/navigation-history.md +++ b/docs/tutorial/navigation-history.md @@ -74,7 +74,6 @@ if (navigationHistory.canGoToOffset(2)) { A common flow is that you want to restore the history of a webContents - for instance to implement an "undo close tab" feature. To do so, you can call `navigationHistory.restore({ index, entries })`. This will restore the webContent's navigation history and the webContents location in said history, meaning that `goBack()` and `goForward()` navigate you through the stack as expected. ```js @ts-type={navigationHistory:Electron.NavigationHistory} - const firstWindow = new BrowserWindow() // Later, you want a second window to have the same history and navigation position diff --git a/docs/tutorial/performance.md b/docs/tutorial/performance.md index bb7a80aa84..bc470fc350 100644 --- a/docs/tutorial/performance.md +++ b/docs/tutorial/performance.md @@ -175,6 +175,7 @@ you might write code that eagerly loads dependencies: ```js title='parser.js' @ts-expect-error=[2] const fs = require('node:fs') + const fooParser = require('foo-parser') class Parser { diff --git a/docs/tutorial/process-model.md b/docs/tutorial/process-model.md index e8dd209cce..e8d4d82a35 100644 --- a/docs/tutorial/process-model.md +++ b/docs/tutorial/process-model.md @@ -242,8 +242,8 @@ These aliases have no impact on runtime, but can be used for typechecking and autocomplete. ```js title="Usage example" -const { app } = require('electron/main') const { shell } = require('electron/common') +const { app } = require('electron/main') ``` [window-mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Window diff --git a/docs/tutorial/security.md b/docs/tutorial/security.md index 7923077c69..3b5c554b88 100644 --- a/docs/tutorial/security.md +++ b/docs/tutorial/security.md @@ -281,7 +281,8 @@ security-conscious developers might want to assume the very opposite. ```js title='main.js (Main Process)' const { session } = require('electron') -const { URL } = require('url') + +const { URL } = require('node:url') session .fromPartition('some-partition') @@ -611,9 +612,10 @@ sometimes be fooled - a `startsWith('https://example.com')` test would let `https://example.com.attacker.com` through. ```js title='main.js (Main Process)' -const { URL } = require('url') const { app } = require('electron') +const { URL } = require('node:url') + app.on('web-contents-created', (event, contents) => { contents.on('will-navigate', (event, navigationUrl) => { const parsedUrl = new URL(navigationUrl) @@ -690,12 +692,14 @@ leveraged to execute arbitrary commands. ```js title='main.js (Main Process)' @ts-type={USER_CONTROLLED_DATA_HERE:string} // Bad const { shell } = require('electron') + shell.openExternal(USER_CONTROLLED_DATA_HERE) ``` ```js title='main.js (Main Process)' // Good const { shell } = require('electron') + shell.openExternal('https://example.com/index.html') ``` diff --git a/docs/tutorial/tutorial-3-preload.md b/docs/tutorial/tutorial-3-preload.md index 0854de8305..32fd88e253 100644 --- a/docs/tutorial/tutorial-3-preload.md +++ b/docs/tutorial/tutorial-3-preload.md @@ -83,6 +83,7 @@ To attach this script to your renderer process, pass its path to the ```js {2,8-10} title="main.js" const { app, BrowserWindow } = require('electron') + const path = require('node:path') const createWindow = () => { @@ -204,6 +205,7 @@ you send out the `invoke` call from the renderer. ```js {1,15} title="main.js" const { app, BrowserWindow, ipcMain } = require('electron/main') + const path = require('node:path') const createWindow = () => { diff --git a/docs/tutorial/windows-taskbar.md b/docs/tutorial/windows-taskbar.md index 5232e4d95d..e48b37c4d9 100644 --- a/docs/tutorial/windows-taskbar.md +++ b/docs/tutorial/windows-taskbar.md @@ -126,6 +126,7 @@ following lines: ```js const { BrowserWindow, nativeImage } = require('electron') + const path = require('node:path') const win = new BrowserWindow() diff --git a/package.json b/package.json index bdb74a9c48..93119e7166 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "eslint": "^8.57.1", "eslint-config-standard": "^17.1.0", "eslint-plugin-import": "^2.30.0", + "eslint-plugin-markdown": "^5.1.0", "eslint-plugin-mocha": "^10.5.0", "eslint-plugin-n": "^16.6.2", "eslint-plugin-node": "^11.1.0", diff --git a/script/lint.js b/script/lint.js index 63459f47ef..e37a2387aa 100755 --- a/script/lint.js +++ b/script/lint.js @@ -73,6 +73,24 @@ function spawnAndCheckExitCode (cmd, args, opts) { } } +async function runEslint (eslint, filenames, { fix, verbose }) { + const formatter = await eslint.loadFormatter(); + let successCount = 0; + const results = await eslint.lintFiles(filenames); + for (const result of results) { + successCount += result.errorCount === 0 ? 1 : 0; + if (verbose && result.errorCount === 0 && result.warningCount === 0) { + console.log(`${result.filePath}: no errors or warnings`); + } + } + console.log(formatter.format(results)); + if (fix) { + await ESLint.outputFixes(results); + } + + return successCount === filenames.length; +} + function cpplint (args) { args.unshift(`--root=${SOURCE_ROOT}`); const cmd = IS_WINDOWS ? 'cpplint.bat' : 'cpplint.py'; @@ -146,20 +164,8 @@ const LINTERS = [{ fix: opts.fix, resolvePluginsRelativeTo: ELECTRON_ROOT }); - const formatter = await eslint.loadFormatter(); - let successCount = 0; - const results = await eslint.lintFiles(filenames); - for (const result of results) { - successCount += result.errorCount === 0 ? 1 : 0; - if (opts.verbose && result.errorCount === 0 && result.warningCount === 0) { - console.log(`${result.filePath}: no errors or warnings`); - } - } - console.log(formatter.format(results)); - if (opts.fix) { - await ESLint.outputFixes(results); - } - if (successCount !== filenames.length) { + const clean = await runEslint(eslint, filenames, { fix: opts.fix, verbose: opts.verbose }); + if (!clean) { console.error('Linting had errors'); process.exit(1); } @@ -363,6 +369,26 @@ const LINTERS = [{ } } + const eslint = new ESLint({ + // Do not use the lint cache on CI builds + cache: !process.env.CI, + cacheLocation: `node_modules/.eslintcache.${crypto.createHash('md5').update(fs.readFileSync(__filename)).digest('hex')}`, + fix: opts.fix, + overrideConfigFile: path.join(ELECTRON_ROOT, 'docs', '.eslintrc.json'), + resolvePluginsRelativeTo: ELECTRON_ROOT + }); + const clean = await runEslint( + eslint, + docs.filter( + // TODO(dsanders11): Once we move to newer ESLint and the flat config, + // switch to using `ignorePatterns` and `warnIgnore: false` instead of + // explicitly filtering out this file that we don't want to lint + (filename) => !filename.endsWith('docs/breaking-changes.md') + ), + { fix: opts.fix, verbose: opts.verbose } + ); + errors ||= !clean; + if (errors) { process.exit(1); } diff --git a/yarn.lock b/yarn.lock index 18de5022d5..48093eab0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -953,6 +953,13 @@ "@types/linkify-it" "^5" "@types/mdurl" "^2" +"@types/mdast@^3.0.0": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== + dependencies: + "@types/unist" "^2" + "@types/mdast@^4.0.0": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" @@ -1065,6 +1072,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/unist@^2": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" @@ -1856,16 +1868,31 @@ chalk@^5.0.0, chalk@^5.3.0: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + character-entities-legacy@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + character-entities@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.0.tgz#508355fcc8c73893e0909efc1a44d28da2b6fdf3" integrity sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA== +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + character-reference-invalid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.0.tgz#a0bdeb89c051fe7ed5d3158b2f06af06984f2813" @@ -2650,6 +2677,13 @@ eslint-plugin-import@^2.30.0: semver "^6.3.1" tsconfig-paths "^3.15.0" +eslint-plugin-markdown@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-markdown/-/eslint-plugin-markdown-5.1.0.tgz#e87724118e822cdfc89cbf1edb40248a3bc9aece" + integrity sha512-SJeyKko1K6GwI0AN6xeCDToXDkfKZfXcexA6B+O2Wr2btUS9GrC+YgwSyVli5DJnctUHjFXcQ2cqTaAmVoLi2A== + dependencies: + mdast-util-from-markdown "^0.8.5" + eslint-plugin-mocha@^10.5.0: version "10.5.0" resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz#0aca8d709e7cddef566e0dc252f6b02e307a2b7e" @@ -3649,11 +3683,24 @@ interpret@^3.1.1: resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + is-alphabetical@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.0.tgz#ef6e2caea57c63450fffc7abb6cbdafc5eb96e96" integrity sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w== +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-alphanumerical@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz#0fbfeb6a72d21d91143b3d182bf6cf5909ee66f6" @@ -3760,6 +3807,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-decimal@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.0.tgz#db1140337809fd043a056ae40a9bd1cdc563034c" @@ -3794,6 +3846,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-hexadecimal@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz#8e1ec9f48fe3eabd90161109856a23e0907a65d5" @@ -4418,6 +4475,17 @@ mdast-comment-marker@^1.0.0: resolved "https://registry.yarnpkg.com/mdast-comment-marker/-/mdast-comment-marker-1.1.1.tgz#9c9c18e1ed57feafc1965d92b028f37c3c8da70d" integrity sha512-TWZDaUtPLwKX1pzDIY48MkSUQRDwX/HqbTB4m3iYdL/zosi/Z6Xqfdv0C0hNVKvzrPjZENrpWDt4p4odeVO0Iw== +mdast-util-from-markdown@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + mdast-util-from-markdown@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz#32a6e8f512b416e1f51eb817fc64bd867ebcd9cc" @@ -4486,6 +4554,11 @@ mdast-util-to-string@^1.0.2: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.6.tgz#7d85421021343b33de1552fc71cb8e5b4ae7536d" integrity sha512-868pp48gUPmZIhfKrLbaDneuzGiw3OTDjHc5M1kAepR2CWBJ+HpEsm252K4aXdiP5coVZaJPOqGtVU6Po8xnXg== +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + mdast-util-to-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" @@ -4821,6 +4894,14 @@ micromark@^4.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark@~2.11.0: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@4.0.8, micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -5299,6 +5380,18 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-entities@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.2.tgz#61d46f5ed28e4ee62e9ddc43d6b010188443f159"