chore: add custom rule for formatting comments (#8777)

This commit is contained in:
jrandolf 2022-08-12 14:15:26 +02:00 committed by GitHub
parent 73221042db
commit ddbe88b887
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2613 additions and 2318 deletions

95
.eslintplugin.js Normal file
View File

@ -0,0 +1,95 @@
const prettier = require('prettier');
const cleanupBlockComment = value => {
return value
.trim()
.split('\n')
.map(value => {
value = value.trim();
if (value.startsWith('*')) {
value = value.slice(1);
if (value.startsWith(' ')) {
value = value.slice(1);
}
}
return value.trimEnd();
})
.join('\n')
.trim();
};
const format = (value, offset, prettierOptions) => {
return prettier
.format(value, {
...prettierOptions,
// This is the print width minus 3 (the length of ` * `) and the offset.
printWidth: prettierOptions.printWidth - (offset + 3),
})
.trim();
};
const buildBlockComment = (value, offset) => {
const spaces = ' '.repeat(offset);
const lines = value.split('\n').map(line => {
return ` * ${line}`;
});
lines.unshift('/**');
lines.push(' */');
lines.forEach((line, i) => {
lines[i] = `${spaces}${line}`;
});
return lines.join('\n');
};
/**
* @type import("eslint").Rule.RuleModule
*/
const rule = {
meta: {
type: 'suggestion',
docs: {
description: 'Enforce Prettier formatting on comments',
recommended: false,
},
fixable: 'code',
schema: [],
messages: {},
},
create(context) {
const prettierOptions = {
printWidth: 80,
...prettier.resolveConfig.sync(context.getPhysicalFilename()),
parser: 'markdown',
};
for (const comment of context.getSourceCode().getAllComments()) {
switch (comment.type) {
case 'Block': {
const offset = comment.loc.start.column;
const value = cleanupBlockComment(comment.value);
const formattedValue = format(value, offset, prettierOptions);
if (formattedValue !== value) {
context.report({
node: comment,
message: `Comment is not formatted correctly.`,
fix(fixer) {
return fixer.replaceText(
comment,
buildBlockComment(formattedValue, offset).trimStart()
);
},
});
}
break;
}
}
}
return {};
},
};
module.exports = {
rules: {
'prettier-comments': rule,
},
};

View File

@ -1,12 +1,3 @@
// TODO: Enable this at some point.
// const RESTRICTED_UNDERSCORED_IDENTIFIERS = [
// 'PropertyDefinition > Identifier[name=/^_[a-z].*$/]',
// ].map((selector) => ({
// selector,
// message:
// 'Use private fields (fields prefixed with #) and an appropriate getter/setter.',
// }));
module.exports = {
root: true,
env: {
@ -132,8 +123,10 @@ module.exports = {
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
plugins: ['eslint-plugin-tsdoc'],
plugins: ['eslint-plugin-tsdoc', 'local'],
rules: {
// Keeps comments formatted.
'local/prettier-comments': 2,
// Brackets keep code readable.
curly: [2, 'all'],
// Brackets keep code readable and `return` intentions clear.
@ -189,9 +182,6 @@ module.exports = {
selector: "CallExpression[callee.name='require']",
message: '`require` statements are not allowed. Use `import`.',
},
// Don't allow underscored declarations on camelCased variables/properties.
// ...RESTRICTED_UNDERSCORED_IDENTIFIERS,
],
},
},

View File

@ -28,7 +28,7 @@ An AXNode object representing the snapshot.
## Remarks
\*\*NOTE\*\* The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers. Puppeteer will discard them as well for an easier to process tree, unless `interestingOnly` is set to `false`.
**NOTE** The Chromium accessibility tree contains nodes that go unused on most platforms and by most screen readers. Puppeteer will discard them as well for an easier to process tree, unless `interestingOnly` is set to `false`.
## Example 1

View File

@ -30,7 +30,7 @@ const browser = await puppeteer.launch({
});
```
\*\*NOTE\*\* BrowserFetcher is not designed to work concurrently with other instances of BrowserFetcher that share the same downloads directory.
**NOTE** BrowserFetcher is not designed to work concurrently with other instances of BrowserFetcher that share the same downloads directory.
## Methods

View File

@ -29,4 +29,4 @@ Promise<void>
If `key` is a single character and no modifier keys besides `Shift` are being held down, a `keypress`/`input` event will also be generated. The `text` option can be specified to force an input event to be generated.
\*\*NOTE\*\* Modifier keys DO affect `elementHandle.press`. Holding down `Shift` will type the text in upper case.
**NOTE** Modifier keys DO affect `elementHandle.press`. Holding down `Shift` will type the text in upper case.

View File

@ -24,4 +24,4 @@ Throws if the object cannot be serialized due to circularity.
## Remarks
If the object has a `toJSON` function, it \*will not\* be called.
If the object has a `toJSON` function, it **will not** be called.

View File

@ -31,7 +31,7 @@ await page.mouse.move(0, 0);
await page.mouse.up();
```
\*\*Note\*\*: The mouse events trigger synthetic `MouseEvent`s. This means that it does not fully replicate the functionality of what a normal user would be able to do with their mouse.
**Note**: The mouse events trigger synthetic `MouseEvent`s. This means that it does not fully replicate the functionality of what a normal user would be able to do with their mouse.
For example, dragging and selecting text is not possible using `page.mouse`. Instead, you can use the [\`DocumentOrShadowRoot.getSelection()\`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/getSelection) functionality implemented in the platform.
@ -67,7 +67,7 @@ await page.evaluate(() => {
});
```
\*\*Note\*\*: If you want access to the clipboard API, you have to give it permission to do so:
**Note**: If you want access to the clipboard API, you have to give it permission to do so:
```ts
await browser

View File

@ -40,7 +40,9 @@ The argument `options` might have the following properties:
- `referer` : Referer header value. If provided it will take preference over the referer header value set by [page.setExtraHTTPHeaders()](./puppeteer.page.setextrahttpheaders.md).
`page.goto` will throw an error if: - there's an SSL error (e.g. in case of self-signed certificates). - target URL is invalid. - the timeout is exceeded during navigation. - the remote server does not respond or is unreachable. - the main resource failed to load.
`page.goto` will throw an error if:
- there's an SSL error (e.g. in case of self-signed certificates). - target URL is invalid. - the timeout is exceeded during navigation. - the remote server does not respond or is unreachable. - the main resource failed to load.
`page.goto` will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling response.status().

View File

@ -27,9 +27,9 @@ class Page {
## Parameters
| Parameter | Type | Description |
| ------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| pageFunction | Func \| string | Function to be evaluated in browser context |
| options | { timeout?: number; polling?: string \| number; } | <i>(Optional)</i> Optional waiting parameters - <code>polling</code> - An interval at which the <code>pageFunction</code> is executed, defaults to <code>raf</code>. If <code>polling</code> is a number, then it is treated as an interval in milliseconds at which the function would be executed. If polling is a string, then it can be one of the following values: - <code>raf</code> - to constantly execute <code>pageFunction</code> in <code>requestAnimationFrame</code> callback. This is the tightest polling mode which is suitable to observe styling changes. - <code>mutation</code>- to execute pageFunction on every DOM mutation. - <code>timeout</code> - maximum time to wait for in milliseconds. Defaults to <code>30000</code> (30 seconds). Pass <code>0</code> to disable timeout. The default value can be changed by using the [Page.setDefaultTimeout()](./puppeteer.page.setdefaulttimeout.md) method. |
| options | { timeout?: number; polling?: string \| number; } | <p><i>(Optional)</i> Optional waiting parameters</p><p>- <code>polling</code> - An interval at which the <code>pageFunction</code> is executed, defaults to <code>raf</code>. If <code>polling</code> is a number, then it is treated as an interval in milliseconds at which the function would be executed. If polling is a string, then it can be one of the following values: - <code>raf</code> - to constantly execute <code>pageFunction</code> in <code>requestAnimationFrame</code> callback. This is the tightest polling mode which is suitable to observe styling changes. - <code>mutation</code>- to execute pageFunction on every DOM mutation. - <code>timeout</code> - maximum time to wait for in milliseconds. Defaults to <code>30000</code> (30 seconds). Pass <code>0</code> to disable timeout. The default value can be changed by using the [Page.setDefaultTimeout()](./puppeteer.page.setdefaulttimeout.md) method.</p> |
| args | Params | Arguments to pass to <code>pageFunction</code> |
**Returns:**

View File

@ -24,7 +24,9 @@ class Page {
Promise&lt;[HTTPResponse](./puppeteer.httpresponse.md) \| null&gt;
A `Promise` which resolves to the main resource response. - In case of multiple redirects, the navigation will resolve with the response of the last redirect. - In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with `null`.
A `Promise` which resolves to the main resource response.
- In case of multiple redirects, the navigation will resolve with the response of the last redirect. - In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with `null`.
## Remarks

View File

@ -19,7 +19,9 @@ export declare type PaperFormat =
## Remarks
The sizes of each format are as follows: - `Letter`: 8.5in x 11in
The sizes of each format are as follows:
- `Letter`: 8.5in x 11in
- `Legal`: 8.5in x 14in

View File

@ -4,7 +4,9 @@ sidebar_label: PDFOptions.headerTemplate
# PDFOptions.headerTemplate property
HTML template for the print header. Should be valid HTML with the following classes used to inject values into them: - `date` formatted print date
HTML template for the print header. Should be valid HTML with the following classes used to inject values into them:
- `date` formatted print date
- `title` document title

View File

@ -15,11 +15,11 @@ export interface PDFOptions
## Properties
| Property | Modifiers | Type | Description |
| --------------------------------------------------------------------- | --------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --------------------------------------------------------------------- | --------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [displayHeaderFooter?](./puppeteer.pdfoptions.displayheaderfooter.md) | | boolean | <i>(Optional)</i> Whether to show the header and footer. |
| [footerTemplate?](./puppeteer.pdfoptions.footertemplate.md) | | string | <i>(Optional)</i> HTML template for the print footer. Has the same constraints and support for special classes as [PDFOptions.headerTemplate](./puppeteer.pdfoptions.headertemplate.md). |
| [format?](./puppeteer.pdfoptions.format.md) | | [PaperFormat](./puppeteer.paperformat.md) | <i>(Optional)</i> |
| [headerTemplate?](./puppeteer.pdfoptions.headertemplate.md) | | string | <p><i>(Optional)</i> HTML template for the print header. Should be valid HTML with the following classes used to inject values into them: - <code>date</code> formatted print date</p><p>- <code>title</code> document title</p><p>- <code>url</code> document location</p><p>- <code>pageNumber</code> current page number</p><p>- <code>totalPages</code> total pages in the document</p> |
| [headerTemplate?](./puppeteer.pdfoptions.headertemplate.md) | | string | <p><i>(Optional)</i> HTML template for the print header. Should be valid HTML with the following classes used to inject values into them:</p><p>- <code>date</code> formatted print date</p><p>- <code>title</code> document title</p><p>- <code>url</code> document location</p><p>- <code>pageNumber</code> current page number</p><p>- <code>totalPages</code> total pages in the document</p> |
| [height?](./puppeteer.pdfoptions.height.md) | | string \| number | <i>(Optional)</i> Sets the height of paper. You can pass in a number or a string with a unit. |
| [landscape?](./puppeteer.pdfoptions.landscape.md) | | boolean | <i>(Optional)</i> Whether to print in landscape orientation. |
| [margin?](./puppeteer.pdfoptions.margin.md) | | [PDFMargin](./puppeteer.pdfmargin.md) | <i>(Optional)</i> Set the PDF margins. |

View File

@ -26,4 +26,4 @@ A path where Puppeteer expects to find the bundled browser. The browser binary m
## Remarks
\*\*NOTE\*\* `puppeteer.executablePath()` is affected by the `PUPPETEER_EXECUTABLE_PATH` and `PUPPETEER_CHROMIUM_REVISION` environment variables.
**NOTE** `puppeteer.executablePath()` is affected by the `PUPPETEER_EXECUTABLE_PATH` and `PUPPETEER_CHROMIUM_REVISION` environment variables.

View File

@ -28,7 +28,7 @@ Promise which resolves to browser instance.
## Remarks
\*\*NOTE\*\* Puppeteer can also be used to control the Chrome browser, but it works best with the version of Chromium it is bundled with. There is no guarantee it will work with any other version. Use `executablePath` option with extreme caution. If Google Chrome (rather than Chromium) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. In `puppeteer.launch([options])`, any mention of Chromium also applies to Chrome. See [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [This article](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
**NOTE** Puppeteer can also be used to control the Chrome browser, but it works best with the version of Chromium it is bundled with. There is no guarantee it will work with any other version. Use `executablePath` option with extreme caution. If Google Chrome (rather than Chromium) is preferred, a [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested. In `puppeteer.launch([options])`, any mention of Chromium also applies to Chrome. See [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [This article](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.
## Example

13
package-lock.json generated
View File

@ -54,6 +54,7 @@
"eslint-config-prettier": "8.5.0",
"eslint-formatter-codeframe": "7.32.1",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-local": "^1.0.0",
"eslint-plugin-mocha": "10.1.0",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-tsdoc": "0.2.16",
@ -2624,6 +2625,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/eslint-plugin-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz",
"integrity": "sha512-bcwcQnKL/Iw5Vi/F2lG1he5oKD2OGjhsLmrcctkWrWq5TujgiaYb0cj3pZgr3XI54inNVnneOFdAx1daLoYLJQ==",
"dev": true
},
"node_modules/eslint-plugin-mocha": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.1.0.tgz",
@ -9061,6 +9068,12 @@
}
}
},
"eslint-plugin-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz",
"integrity": "sha512-bcwcQnKL/Iw5Vi/F2lG1he5oKD2OGjhsLmrcctkWrWq5TujgiaYb0cj3pZgr3XI54inNVnneOFdAx1daLoYLJQ==",
"dev": true
},
"eslint-plugin-mocha": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.1.0.tgz",

View File

@ -113,6 +113,7 @@
"eslint-config-prettier": "8.5.0",
"eslint-formatter-codeframe": "7.32.1",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-local": "1.0.0",
"eslint-plugin-mocha": "10.1.0",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-tsdoc": "0.2.16",

View File

@ -152,6 +152,7 @@ export class Accessibility {
*
* @example
* An example of dumping the entire accessibility tree:
*
* ```ts
* const snapshot = await page.accessibility.snapshot();
* console.log(snapshot);
@ -159,14 +160,14 @@ export class Accessibility {
*
* @example
* An example of logging the focused node's name:
*
* ```ts
* const snapshot = await page.accessibility.snapshot();
* const node = findFocusedNode(snapshot);
* console.log(node && node.name);
*
* function findFocusedNode(node) {
* if (node.focused)
* return node;
* if (node.focused) return node;
* for (const child of node.children || []) {
* const foundNode = findFocusedNode(child);
* return foundNode;

View File

@ -59,11 +59,12 @@ function isKnownAttribute(
return knownAttributes.has(attribute);
}
/*
/**
* The selectors consist of an accessible name to query for and optionally
* further aria attributes on the form `[<attribute>=<value>]`.
* Currently, we only support the `name` and `role` attribute.
* The following examples showcase how the syntax works wrt. querying:
*
* - 'title[role="heading"]' queries for elements with name 'title' and role 'heading'.
* - '[role="img"]' queries for elements with role 'img' and any name.
* - 'label' queries for elements with name 'label' and any role.

View File

@ -181,8 +181,8 @@ export const enum BrowserEmittedEvents {
* emit various events which are documented in the {@link BrowserEmittedEvents} enum.
*
* @example
*
* An example of using a {@link Browser} to create a {@link Page}:
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -195,8 +195,8 @@ export const enum BrowserEmittedEvents {
* ```
*
* @example
*
* An example of disconnecting from and reconnecting to a {@link Browser}:
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -411,6 +411,7 @@ export class Browser extends EventEmitter {
* browser contexts.
*
* @example
*
* ```ts
* (async () => {
* const browser = await puppeteer.launch();
@ -631,9 +632,12 @@ export class Browser extends EventEmitter {
* @example
*
* An example of finding a target for a page opened via `window.open`:
*
* ```ts
* await page.evaluate(() => window.open('https://www.example.com/'));
* const newWindowTarget = await browser.waitForTarget(target => target.url() === 'https://www.example.com/');
* const newWindowTarget = await browser.waitForTarget(
* target => target.url() === 'https://www.example.com/'
* );
* ```
*/
async waitForTarget(
@ -788,6 +792,7 @@ export const enum BrowserContextEmittedEvents {
* method. "Incognito" browser contexts don't write any browsing data to disk.
*
* @example
*
* ```ts
* // Create a new incognito browser context
* const context = await browser.createIncognitoBrowserContext();
@ -798,6 +803,7 @@ export const enum BrowserContextEmittedEvents {
* // Dispose context once it's no longer needed.
* await context.close();
* ```
*
* @public
*/
export class BrowserContext extends EventEmitter {
@ -829,9 +835,12 @@ export class BrowserContext extends EventEmitter {
*
* @example
* An example of finding a target for a page opened via `window.open`:
*
* ```ts
* await page.evaluate(() => window.open('https://www.example.com/'));
* const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/');
* const newWindowTarget = await browserContext.waitForTarget(
* target => target.url() === 'https://www.example.com/'
* );
* ```
*
* @param predicate - A function to be run for every target
@ -891,9 +900,12 @@ export class BrowserContext extends EventEmitter {
/**
* @example
*
* ```ts
* const context = browser.defaultBrowserContext();
* await context.overridePermissions('https://html5demos.com', ['geolocation']);
* await context.overridePermissions('https://html5demos.com', [
* 'geolocation',
* ]);
* ```
*
* @param origin - The origin to grant permissions to, e.g. "https://example.com".
@ -923,6 +935,7 @@ export class BrowserContext extends EventEmitter {
* Clears all permission overrides for the browser context.
*
* @example
*
* ```ts
* const context = browser.defaultBrowserContext();
* context.overridePermissions('https://example.com', ['clipboard-read']);

View File

@ -280,14 +280,17 @@ export const CDPSessionEmittedEvents = {
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}.
*
* @example
*
* ```ts
* const client = await page.target().createCDPSession();
* await client.send('Animation.enable');
* client.on('Animation.animationCreated', () => console.log('Animation created!'));
* client.on('Animation.animationCreated', () =>
* console.log('Animation created!')
* );
* const response = await client.send('Animation.getPlaybackRate');
* console.log('playback rate is ' + response.playbackRate);
* await client.send('Animation.setPlaybackRate', {
* playbackRate: response.playbackRate / 2
* playbackRate: response.playbackRate / 2,
* });
* ```
*

View File

@ -98,11 +98,12 @@ export interface CSSCoverageOptions {
* @example
* An example of using JavaScript and CSS coverage to get percentage of initially
* executed code:
*
* ```ts
* // Enable both JavaScript and CSS coverage
* await Promise.all([
* page.coverage.startJSCoverage(),
* page.coverage.startCSSCoverage()
* page.coverage.startCSSCoverage(),
* ]);
* // Navigate to page
* await page.goto('https://example.com');
@ -116,11 +117,11 @@ export interface CSSCoverageOptions {
* const coverage = [...jsCoverage, ...cssCoverage];
* for (const entry of coverage) {
* totalBytes += entry.text.length;
* for (const range of entry.ranges)
* usedBytes += range.end - range.start - 1;
* for (const range of entry.ranges) usedBytes += range.end - range.start - 1;
* }
* console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`);
* console.log(`Bytes used: ${(usedBytes / totalBytes) * 100}%`);
* ```
*
* @public
*/
export class Coverage {

View File

@ -60,6 +60,7 @@ export async function importDebug(): Promise<typeof import('debug')> {
* ```
*
* @example
*
* ```
* const log = debug('Page');
*

View File

@ -24,6 +24,7 @@ import {Protocol} from 'devtools-protocol';
* @remarks
*
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -38,6 +39,7 @@ import {Protocol} from 'devtools-protocol';
* page.evaluate(() => alert('1'));
* })();
* ```
*
* @public
*/
export class Dialog {

View File

@ -142,10 +142,15 @@ export class ElementHandle<
* the promise resolves.
*
* @example
*
* ```ts
* const tweetHandle = await page.$('.tweet');
* expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
* expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
* expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe(
* '100'
* );
* expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe(
* '10'
* );
* ```
*
* @param selector - The selector to query for.
@ -186,17 +191,21 @@ export class ElementHandle<
*
* @example
* HTML:
*
* ```html
* <div class="feed">
* <div class="tweet">Hello!</div>
* <div class="tweet">Hi!</div>
* </div>
* ```
*
* JavaScript:
*
* ```js
* const feedHandle = await page.$('.feed');
* expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText)))
* .toEqual(['Hello!', 'Hi!']);
* expect(
* await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))
* ).toEqual(['Hello!', 'Hi!']);
* ```
*
* @param selector - The selector to query for.
@ -251,6 +260,7 @@ export class ElementHandle<
* navigations or if the element is detached from DOM.
*
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -258,16 +268,22 @@ export class ElementHandle<
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page.mainFrame()
* page
* .mainFrame()
* .waitForSelector('img')
* .then(() => console.log('First URL with image: ' + currentURL));
*
* for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com']) {
* for (currentURL of [
* 'https://example.com',
* 'https://google.com',
* 'https://bbc.com',
* ]) {
* await page.goto(currentURL);
* }
* await browser.close();
* })();
* ```
*
* @param selector - The selector to query and wait for.
* @param options - Options for customizing waiting behavior.
* @returns An element matching the given selector.
@ -311,6 +327,7 @@ export class ElementHandle<
* automatically.
*
* This method works across navigation
*
* ```ts
* const puppeteer = require('puppeteer');
* (async () => {
@ -330,6 +347,7 @@ export class ElementHandle<
* await browser.close();
* })();
* ```
*
* @param xpath - A
* {@link https://developer.mozilla.org/en-US/docs/Web/XPath | xpath} of an
* element to wait for
@ -665,10 +683,12 @@ export class ElementHandle<
* throws an error.
*
* @example
*
* ```ts
* handle.select('blue'); // single selection
* handle.select('red', 'green', 'blue'); // multiple selections
* ```
*
* @param values - Values of options to select. If the `<select>` has the
* `multiple` attribute, all values are considered, otherwise only the first
* one is taken into account.
@ -814,6 +834,7 @@ export class ElementHandle<
* use {@link ElementHandle.press}.
*
* @example
*
* ```ts
* await elementHandle.type('Hello'); // Types instantly
* await elementHandle.type('World', {delay: 100}); // Types slower, like a user

View File

@ -65,6 +65,7 @@ export interface PuppeteerErrors {
*
* @example
* An example of handling a timeout error:
*
* ```ts
* try {
* await page.waitForSelector('.foo');

View File

@ -102,6 +102,7 @@ export class ExecutionContext {
* Evaluates the given function.
*
* @example
*
* ```ts
* const executionContext = await page.mainFrame().executionContext();
* const result = await executionContext.evaluate(() => Promise.resolve(8 * 7))* ;
@ -110,17 +111,21 @@ export class ExecutionContext {
*
* @example
* A string can also be passed in instead of a function:
*
* ```ts
* console.log(await executionContext.evaluate('1 + 2')); // prints "3"
* ```
*
* @example
* Handles can also be passed as `args`. They resolve to their referenced object:
*
* ```ts
* const oneHandle = await executionContext.evaluateHandle(() => 1);
* const twoHandle = await executionContext.evaluateHandle(() => 2);
* const result = await executionContext.evaluate(
* (a, b) => a + b, oneHandle, twoHandle
* (a, b) => a + b,
* oneHandle,
* twoHandle
* );
* await oneHandle.dispose();
* await twoHandle.dispose();
@ -153,27 +158,29 @@ export class ExecutionContext {
* `Map`) and requires further manipulation.
*
* @example
*
* ```ts
* const context = await page.mainFrame().executionContext();
* const handle: JSHandle<typeof globalThis> = await context.evaluateHandle(() =>
* Promise.resolve(self)
* const handle: JSHandle<typeof globalThis> = await context.evaluateHandle(
* () => Promise.resolve(self)
* );
* ```
*
* @example
* A string can also be passed in instead of a function.
*
* ```ts
* const handle: JSHandle<number> = await context.evaluateHandle('1 + 2');
* ```
*
* @example
* Handles can also be passed as `args`. They resolve to their referenced object:
*
* ```ts
* const bodyHandle: ElementHandle<HTMLBodyElement> = await context.evaluateHandle(
* () => {
* const bodyHandle: ElementHandle<HTMLBodyElement> =
* await context.evaluateHandle(() => {
* return document.body;
* }
* );
* });
* const stringHandle: JSHandle<string> = await context.evaluateHandle(
* body => body.innerHTML,
* body
@ -372,9 +379,10 @@ export class ExecutionContext {
* given prototype.
*
* @example
*
* ```ts
* // Create a Map object
* await page.evaluate(() => window.map = new Map());
* await page.evaluate(() => (window.map = new Map()));
* // Get a handle to the Map object prototype
* const mapPrototype = await page.evaluateHandle(() => Map.prototype);
* // Query all map instances into an array

View File

@ -29,6 +29,7 @@ import {ElementHandle} from './ElementHandle.js';
* subsequent file choosers from appearing.
*
* @example
*
* ```ts
* const [fileChooser] = await Promise.all([
* page.waitForFileChooser(),

View File

@ -36,6 +36,7 @@ import {EventEmitter} from './EventEmitter.js';
* because Firefox's CDP implementation does not support auto-attach.
*
* Firefox does not support targetInfoChanged and detachedFromTarget events:
*
* - https://bugzilla.mozilla.org/show_bug.cgi?id=1610855
* - https://bugzilla.mozilla.org/show_bug.cgi?id=1636979
* @internal

View File

@ -861,6 +861,7 @@ export class Frame {
* to change the URL is considered a navigation.
*
* @example
*
* ```ts
* const [response] = await Promise.all([
* // The navigation promise resolves after navigation has finished
@ -988,6 +989,7 @@ export class Frame {
* the promise resolves.
*
* @example
*
* ```ts
* const searchValue = await frame.$eval('#search', el => el.value);
* ```
@ -1021,6 +1023,7 @@ export class Frame {
* the promise resolves.
*
* @example
*
* ```js
* const divsCounts = await frame.$$eval('div', divs => divs.length);
* ```
@ -1062,6 +1065,7 @@ export class Frame {
* This method works across navigations.
*
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -1069,16 +1073,22 @@ export class Frame {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page.mainFrame()
* page
* .mainFrame()
* .waitForSelector('img')
* .then(() => console.log('First URL with image: ' + currentURL));
*
* for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com']) {
* for (currentURL of [
* 'https://example.com',
* 'https://google.com',
* 'https://bbc.com',
* ]) {
* await page.goto(currentURL);
* }
* await browser.close();
* })();
* ```
*
* @param selector - The selector to query and wait for.
* @param options - Options for customizing waiting behavior.
* @returns An element matching the given selector.
@ -1131,6 +1141,7 @@ export class Frame {
/**
* @example
* The `waitForFunction` can be used to observe viewport size change:
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -1152,7 +1163,7 @@ export class Frame {
* selector => !!document.querySelector(selector),
* {}, // empty options object
* selector
*);
* );
* ```
*
* @param pageFunction - the function to evaluate in the frame context.
@ -1326,6 +1337,7 @@ export class Frame {
* `selector`.
*
* @example
*
* ```ts
* frame.select('select#colors', 'blue'); // single selection
* frame.select('select#colors', 'red', 'green', 'blue'); // multiple selections
@ -1361,6 +1373,7 @@ export class Frame {
* {@link Keyboard.press}.
*
* @example
*
* ```ts
* await frame.type('#mytextarea', 'Hello'); // Types instantly
* await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user

View File

@ -80,7 +80,6 @@ interface CDPSession extends EventEmitter {
}
/**
*
* Represents an HTTP request sent by a page.
* @remarks
*
@ -426,6 +425,7 @@ export class HTTPRequest {
* Exception is immediately thrown if the request interception is not enabled.
*
* @example
*
* ```ts
* await page.setRequestInterception(true);
* page.on('request', request => {
@ -519,13 +519,14 @@ export class HTTPRequest {
*
* @example
* An example of fulfilling all requests with 404 responses:
*
* ```ts
* await page.setRequestInterception(true);
* page.on('request', request => {
* request.respond({
* status: 404,
* contentType: 'text/plain',
* body: 'Not Found!'
* body: 'Not Found!',
* });
* });
* ```

View File

@ -40,6 +40,7 @@ type KeyDescription = Required<
*
* @example
* An example of holding down `Shift` in order to select and delete some text:
*
* ```ts
* await page.keyboard.type('Hello World!');
* await page.keyboard.press('ArrowLeft');
@ -55,6 +56,7 @@ type KeyDescription = Required<
*
* @example
* An example of pressing `A`
*
* ```ts
* await page.keyboard.down('Shift');
* await page.keyboard.press('KeyA');
@ -230,6 +232,7 @@ export class Keyboard {
* Holding down `Shift` will not type the text in upper case.
*
* @example
*
* ```ts
* page.keyboard.sendCharacter('嗨');
* ```
@ -256,6 +259,7 @@ export class Keyboard {
* Holding down `Shift` will not type the text in upper case.
*
* @example
*
* ```ts
* await page.keyboard.type('Hello'); // Types instantly
* await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
@ -345,6 +349,7 @@ export interface MouseWheelOptions {
* Every `page` object has its own Mouse, accessible with [`page.mouse`](#pagemouse).
*
* @example
*
* ```ts
* // Using page.mouse to trace a 100x100 square.
* await page.mouse.move(0, 0);
@ -365,17 +370,24 @@ export interface MouseWheelOptions {
*
* @example
* For example, if you want to select all content between nodes:
*
* ```ts
* await page.evaluate((from, to) => {
* await page.evaluate(
* (from, to) => {
* const selection = from.getRootNode().getSelection();
* const range = document.createRange();
* range.setStartBefore(from);
* range.setEndAfter(to);
* selection.removeAllRanges();
* selection.addRange(range);
* }, fromJSHandle, toJSHandle);
* },
* fromJSHandle,
* toJSHandle
* );
* ```
*
* If you then would want to copy-paste your selection, you can use the clipboard api:
*
* ```ts
* // The clipboard api does not allow you to copy, unless the tab is focused.
* await page.bringToFront();
@ -386,13 +398,19 @@ export interface MouseWheelOptions {
* return navigator.clipboard.readText();
* });
* ```
*
* **Note**: If you want access to the clipboard API,
* you have to give it permission to do so:
*
* ```ts
* await browser.defaultBrowserContext().overridePermissions(
* '<your origin>', ['clipboard-read', 'clipboard-write']
* );
* await browser
* .defaultBrowserContext()
* .overridePermissions('<your origin>', [
* 'clipboard-read',
* 'clipboard-write',
* ]);
* ```
*
* @public
*/
export class Mouse {
@ -504,8 +522,11 @@ export class Mouse {
*
* @example
* An example of zooming into an element:
*
* ```ts
* await page.goto('https://mdn.mozillademos.org/en-US/docs/Web/API/Element/wheel_event$samples/Scaling_an_element_via_the_wheel?revision=1587366');
* await page.goto(
* 'https://mdn.mozillademos.org/en-US/docs/Web/API/Element/wheel_event$samples/Scaling_an_element_via_the_wheel?revision=1587366'
* );
*
* const elem = await page.$('div');
* const boundingBox = await elem.boundingBox();
@ -514,7 +535,7 @@ export class Mouse {
* boundingBox.y + boundingBox.height / 2
* );
*
* await page.mouse.wheel({ deltaY: -100 })
* await page.mouse.wheel({deltaY: -100});
* ```
*/
async wheel(options: MouseWheelOptions = {}): Promise<void> {

View File

@ -65,6 +65,7 @@ export interface BoundingBox extends Point {
* They are resolved to their referenced object.
*
* @example
*
* ```ts
* const windowHandle = await page.evaluateHandle(() => window);
* ```
@ -177,6 +178,7 @@ export class JSHandle<T = unknown> {
* Gets a map of handles representing the properties of the current handle.
*
* @example
*
* ```ts
* const listHandle = await page.evaluateHandle(() => document.body.children);
* const properties = await listHandle.getProperties();
@ -214,7 +216,7 @@ export class JSHandle<T = unknown> {
* @throws Throws if the object cannot be serialized due to circularity.
*
* @remarks
* If the object has a `toJSON` function, it *will not* be called.
* If the object has a `toJSON` function, it **will not** be called.
*/
async jsonValue(): Promise<T> {
if (!this.#remoteObject.objectId) {

View File

@ -35,7 +35,7 @@ export type NetworkRequestId = string;
* @internal
*/
export class NetworkEventManager {
/*
/**
* There are four possible orders of events:
* A. `_onRequestWillBeSent`
* B. `_onRequestWillBeSent`, `_onRequestPaused`

View File

@ -46,6 +46,7 @@ export type LowerCasePaperFormat =
* @remarks
*
* The sizes of each format are as follows:
*
* - `Letter`: 8.5in x 11in
*
* - `Legal`: 8.5in x 14in
@ -93,6 +94,7 @@ export interface PDFOptions {
/**
* HTML template for the print header. Should be valid HTML with the following
* classes used to inject values into them:
*
* - `date` formatted print date
*
* - `title` document title

View File

@ -234,6 +234,7 @@ export const enum PageEmittedEvents {
*
* @example
* An example of handling `console` event:
*
* ```ts
* page.on('console', msg => {
* for (let i = 0; i < msg.args().length; ++i)
@ -280,6 +281,7 @@ export const enum PageEmittedEvents {
*
* @remarks
* Contains an object with two properties:
*
* - `title`: the title passed to `console.timeStamp`
* - `metrics`: objec containing metrics as key/value pairs. The values will
* be `number`s.
@ -297,19 +299,19 @@ export const enum PageEmittedEvents {
*
* @example
*
*```ts
*const [popup] = await Promise.all([
* ```ts
* const [popup] = await Promise.all([
* new Promise(resolve => page.once('popup', resolve)),
* page.click('a[target=_blank]'),
*]);
*```
* ]);
* ```
*
*```ts
*const [popup] = await Promise.all([
* ```ts
* const [popup] = await Promise.all([
* new Promise(resolve => page.once('popup', resolve)),
* page.evaluate(() => window.open('https://example.com')),
*]);
*```
* ]);
* ```
*/
Popup = 'popup',
/**
@ -406,6 +408,7 @@ export interface PageEventObject {
*
* @example
* This example creates a page, navigates it to a URL, and then saves a screenshot:
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -423,6 +426,7 @@ export interface PageEventObject {
*
* @example
* This example logs a message for a single page `load` event:
*
* ```ts
* page.once('load', () => console.log('Page loaded!'));
* ```
@ -784,6 +788,7 @@ export class Page extends EventEmitter {
* permissions for the page to read its geolocation.
*
* @example
*
* ```ts
* await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
* ```
@ -924,6 +929,7 @@ export class Page extends EventEmitter {
*
* @example
* An example of a naïve request interceptor that aborts all image requests:
*
* ```ts
* const puppeteer = require('puppeteer');
* (async () => {
@ -931,11 +937,12 @@ export class Page extends EventEmitter {
* const page = await browser.newPage();
* await page.setRequestInterception(true);
* page.on('request', interceptedRequest => {
* if (interceptedRequest.url().endsWith('.png') ||
* interceptedRequest.url().endsWith('.jpg'))
* if (
* interceptedRequest.url().endsWith('.png') ||
* interceptedRequest.url().endsWith('.jpg')
* )
* interceptedRequest.abort();
* else
* interceptedRequest.continue();
* else interceptedRequest.continue();
* });
* await page.goto('https://example.com');
* await browser.close();
@ -975,6 +982,7 @@ export class Page extends EventEmitter {
/**
* @param networkConditions - Passing `null` disables network condition emulation.
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
* const slow3G = puppeteer.networkConditions['Slow 3G'];
@ -988,6 +996,7 @@ export class Page extends EventEmitter {
* await browser.close();
* })();
* ```
*
* @remarks
* NOTE: This does not affect WebSockets and WebRTC PeerConnections (see
* https://crbug.com/563644). To set the page offline, you can use
@ -1070,15 +1079,20 @@ export class Page extends EventEmitter {
* recommended as they are easier to debug and use with TypeScript):
*
* @example
*
* ```ts
* const aHandle = await page.evaluateHandle('document')
* const aHandle = await page.evaluateHandle('document');
* ```
*
* @example
* {@link JSHandle} instances can be passed as arguments to the `pageFunction`:
*
* ```ts
* const aHandle = await page.evaluateHandle(() => document.body);
* const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);
* const resultHandle = await page.evaluateHandle(
* body => body.innerHTML,
* aHandle
* );
* console.log(await resultHandle.jsonValue());
* await resultHandle.dispose();
* ```
@ -1088,8 +1102,11 @@ export class Page extends EventEmitter {
* you instead get an {@link ElementHandle} back:
*
* @example
*
* ```ts
* const button = await page.evaluateHandle(() => document.querySelector('button'));
* const button = await page.evaluateHandle(() =>
* document.querySelector('button')
* );
* // can call `click` because `button` is an `ElementHandle`
* await button.click();
* ```
@ -1129,7 +1146,7 @@ export class Page extends EventEmitter {
*
* ```ts
* // Create a Map object
* await page.evaluate(() => window.map = new Map());
* await page.evaluate(() => (window.map = new Map()));
* // Get a handle to the Map object prototype
* const mapPrototype = await page.evaluateHandle(() => Map.prototype);
* // Query all map instances into an array
@ -1139,6 +1156,7 @@ export class Page extends EventEmitter {
* await mapInstances.dispose();
* await mapPrototype.dispose();
* ```
*
* @param prototypeHandle - a handle to the object prototype.
* @returns Promise which resolves to a handle to an array of objects with
* this prototype.
@ -1179,7 +1197,10 @@ export class Page extends EventEmitter {
* ```ts
* // if you don't provide HTMLInputElement here, TS will error
* // as `value` is not on `Element`
* const searchValue = await page.$eval('#search', (el: HTMLInputElement) => el.value);
* const searchValue = await page.$eval(
* '#search',
* (el: HTMLInputElement) => el.value
* );
* ```
*
* The compiler should be able to infer the return type
@ -1192,7 +1213,8 @@ export class Page extends EventEmitter {
* // The compiler can infer the return type in this case, but if it can't
* // or if you want to be more explicit, provide it as the generic type.
* const searchValue = await page.$eval<string>(
* '#search', (el: HTMLInputElement) => el.value
* '#search',
* (el: HTMLInputElement) => el.value
* );
* ```
*
@ -1231,13 +1253,14 @@ export class Page extends EventEmitter {
* resolve and then return its value.
*
* @example
*
* ```ts
* // get the amount of divs on the page
* const divCount = await page.$$eval('div', divs => divs.length);
*
* // get the text content of all the `.options` elements:
* const options = await page.$$eval('div > span.options', options => {
* return options.map(option => option.textContent)
* return options.map(option => option.textContent);
* });
* ```
*
@ -1247,6 +1270,7 @@ export class Page extends EventEmitter {
* specific sub-type:
*
* @example
*
* ```ts
* // if you don't provide HTMLInputElement here, TS will error
* // as `value` is not on `Element`
@ -1260,11 +1284,13 @@ export class Page extends EventEmitter {
* type to tell the compiler what return type you expect from `$$eval`:
*
* @example
*
* ```ts
* // The compiler can infer the return type in this case, but if it can't
* // or if you want to be more explicit, provide it as the generic type.
* const allInputValues = await page.$$eval<string[]>(
* 'input', (elements: HTMLInputElement[]) => elements.map(e => e.textContent)
* 'input',
* (elements: HTMLInputElement[]) => elements.map(e => e.textContent)
* );
* ```
*
@ -1346,6 +1372,7 @@ export class Page extends EventEmitter {
/**
* @example
*
* ```ts
* await page.setCookie(cookieObject1, cookieObject2);
* ```
@ -1424,6 +1451,7 @@ export class Page extends EventEmitter {
*
* @example
* An example of adding an `md5` function into the page:
*
* ```ts
* const puppeteer = require('puppeteer');
* const crypto = require('crypto');
@ -1431,8 +1459,8 @@ export class Page extends EventEmitter {
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* page.on('console', (msg) => console.log(msg.text()));
* await page.exposeFunction('md5', (text) =>
* page.on('console', msg => console.log(msg.text()));
* await page.exposeFunction('md5', text =>
* crypto.createHash('md5').update(text).digest('hex')
* );
* await page.evaluate(async () => {
@ -1447,6 +1475,7 @@ export class Page extends EventEmitter {
*
* @example
* An example of adding a `window.readfile` function into the page:
*
* ```ts
* const puppeteer = require('puppeteer');
* const fs = require('fs');
@ -1454,8 +1483,8 @@ export class Page extends EventEmitter {
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* page.on('console', (msg) => console.log(msg.text()));
* await page.exposeFunction('readfile', async (filePath) => {
* page.on('console', msg => console.log(msg.text()));
* await page.exposeFunction('readfile', async filePath => {
* return new Promise((resolve, reject) => {
* fs.readFile(filePath, 'utf8', (err, text) => {
* if (err) reject(err);
@ -1586,7 +1615,6 @@ export class Page extends EventEmitter {
*
* - `TaskDuration` : Combined duration of all tasks performed by the browser.
*
*
* - `JSHeapUsedSize` : Used JavaScript heap size.
*
* - `JSHeapTotalSize` : Total JavaScript heap size.
@ -1849,6 +1877,7 @@ export class Page extends EventEmitter {
* {@link Page.setExtraHTTPHeaders |page.setExtraHTTPHeaders()}.
*
* `page.goto` will throw an error if:
*
* - there's an SSL error (e.g. in case of self-signed certificates).
* - target URL is invalid.
* - the timeout is exceeded during navigation.
@ -1917,6 +1946,7 @@ export class Page extends EventEmitter {
* you run code that will indirectly cause the page to navigate.
*
* @example
*
* ```ts
* const [response] = await Promise.all([
* page.waitForNavigation(), // The promise resolves after navigation has finished
@ -1932,6 +1962,7 @@ export class Page extends EventEmitter {
* @param options - Navigation parameters which might have the following
* properties:
* @returns A `Promise` which resolves to the main resource response.
*
* - In case of multiple redirects, the navigation will resolve with the
* response of the last redirect.
* - In case of navigation to a different anchor or navigation due to History
@ -1959,19 +1990,21 @@ export class Page extends EventEmitter {
* @param options - Optional waiting parameters
* @returns Promise which resolves to the matched response
* @example
*
* ```ts
* const firstResponse = await page.waitForResponse(
* 'https://example.com/resource'
* );
* const finalResponse = await page.waitForResponse(
* (response) =>
* response =>
* response.url() === 'https://example.com' && response.status() === 200
* );
* const finalResponse = await page.waitForResponse(async (response) => {
* const finalResponse = await page.waitForResponse(async response => {
* return (await response.text()).includes('<html>');
* });
* return finalResponse.ok();
* ```
*
* @remarks
* Optional Waiting Parameters have:
*
@ -2006,19 +2039,21 @@ export class Page extends EventEmitter {
* @param options - Optional waiting parameters
* @returns Promise which resolves to the matched response.
* @example
*
* ```ts
* const firstResponse = await page.waitForResponse(
* 'https://example.com/resource'
* );
* const finalResponse = await page.waitForResponse(
* (response) =>
* response =>
* response.url() === 'https://example.com' && response.status() === 200
* );
* const finalResponse = await page.waitForResponse(async (response) => {
* const finalResponse = await page.waitForResponse(async response => {
* return (await response.text()).includes('<html>');
* });
* return finalResponse.ok();
* ```
*
* @remarks
* Optional Parameter have:
*
@ -2131,11 +2166,13 @@ export class Page extends EventEmitter {
* @param options - Optional waiting parameters
* @returns Promise which resolves to the matched frame.
* @example
*
* ```ts
* const frame = await page.waitForFrame(async (frame) => {
* const frame = await page.waitForFrame(async frame => {
* return frame.name() === 'Test';
* });
* ```
*
* @remarks
* Optional Parameter have:
*
@ -2284,6 +2321,7 @@ export class Page extends EventEmitter {
* don't expect phones to change size, so you should emulate before navigating
* to the page.
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
* const iPhone = puppeteer.devices['iPhone 6'];
@ -2296,6 +2334,7 @@ export class Page extends EventEmitter {
* await browser.close();
* })();
* ```
*
* @remarks List of all available devices is available in the source code:
* {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts | src/common/DeviceDescriptors.ts}.
*/
@ -2343,6 +2382,7 @@ export class Page extends EventEmitter {
* values are `screen`, `print` and `null`. Passing `null` disables CSS media
* emulation.
* @example
*
* ```ts
* await page.evaluate(() => matchMedia('screen').matches);
* // → true
@ -2393,17 +2433,22 @@ export class Page extends EventEmitter {
* objects, emulates CSS media features on the page. Each media feature object
* must have the following properties:
* @example
*
* ```ts
* await page.emulateMediaFeatures([
* { name: 'prefers-color-scheme', value: 'dark' },
* {name: 'prefers-color-scheme', value: 'dark'},
* ]);
* await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches);
* await page.evaluate(
* () => matchMedia('(prefers-color-scheme: dark)').matches
* );
* // → true
* await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches);
* await page.evaluate(
* () => matchMedia('(prefers-color-scheme: light)').matches
* );
* // → false
*
* await page.emulateMediaFeatures([
* { name: 'prefers-reduced-motion', value: 'reduce' },
* {name: 'prefers-reduced-motion', value: 'reduce'},
* ]);
* await page.evaluate(
* () => matchMedia('(prefers-reduced-motion: reduce)').matches
@ -2415,12 +2460,16 @@ export class Page extends EventEmitter {
* // → false
*
* await page.emulateMediaFeatures([
* { name: 'prefers-color-scheme', value: 'dark' },
* { name: 'prefers-reduced-motion', value: 'reduce' },
* {name: 'prefers-color-scheme', value: 'dark'},
* {name: 'prefers-reduced-motion', value: 'reduce'},
* ]);
* await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches);
* await page.evaluate(
* () => matchMedia('(prefers-color-scheme: dark)').matches
* );
* // → true
* await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches);
* await page.evaluate(
* () => matchMedia('(prefers-color-scheme: light)').matches
* );
* // → false
* await page.evaluate(
* () => matchMedia('(prefers-reduced-motion: reduce)').matches
@ -2431,7 +2480,7 @@ export class Page extends EventEmitter {
* );
* // → false
*
* await page.emulateMediaFeatures([{ name: 'color-gamut', value: 'p3' }]);
* await page.emulateMediaFeatures([{name: 'color-gamut', value: 'p3'}]);
* await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches);
* // → true
* await page.evaluate(() => matchMedia('(color-gamut: p3)').matches);
@ -2484,6 +2533,7 @@ export class Page extends EventEmitter {
* If no arguments set, clears idle state emulation.
*
* @example
*
* ```ts
* // set idle emulation
* await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false});
@ -2515,6 +2565,7 @@ export class Page extends EventEmitter {
* Simulates the given vision deficiency on the page.
*
* @example
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -2524,13 +2575,13 @@ export class Page extends EventEmitter {
* await page.goto('https://v8.dev/blog/10-years');
*
* await page.emulateVisionDeficiency('achromatopsia');
* await page.screenshot({ path: 'achromatopsia.png' });
* await page.screenshot({path: 'achromatopsia.png'});
*
* await page.emulateVisionDeficiency('deuteranopia');
* await page.screenshot({ path: 'deuteranopia.png' });
* await page.screenshot({path: 'deuteranopia.png'});
*
* await page.emulateVisionDeficiency('blurredVision');
* await page.screenshot({ path: 'blurred-vision.png' });
* await page.screenshot({path: 'blurred-vision.png'});
*
* await browser.close();
* })();
@ -2572,6 +2623,7 @@ export class Page extends EventEmitter {
* In the case of multiple pages in a single browser, each page can have its
* own viewport size.
* @example
*
* ```ts
* const page = await browser.newPage();
* await page.setViewport({
@ -2653,6 +2705,7 @@ export class Page extends EventEmitter {
* recommended as they are easier to debug and use with TypeScript):
*
* @example
*
* ```ts
* const aHandle = await page.evaluate('1 + 2');
* ```
@ -2705,6 +2758,7 @@ export class Page extends EventEmitter {
* @param args - Arguments to pass to `pageFunction`
* @example
* An example of overriding the navigator.languages property before the page loads:
*
* ```ts
* // preload.js
*
@ -2993,7 +3047,6 @@ export class Page extends EventEmitter {
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust | `-webkit-print-color-adjust`}
* property to force rendering of exact colors.
*
*
* @param options - options for generating the PDF.
*/
async createPDFStream(options: PDFOptions = {}): Promise<Readable> {
@ -3127,12 +3180,14 @@ export class Page extends EventEmitter {
* there's a separate `page.waitForNavigation()` promise to be resolved, you
* may end up with a race condition that yields unexpected results. The
* correct pattern for click and wait for navigation is the following:
*
* ```ts
* const [response] = await Promise.all([
* page.waitForNavigation(waitOptions),
* page.click(selector, clickOptions),
* ]);
* ```
*
* Shortcut for {@link Frame.click | page.mainFrame().click(selector[, options]) }.
* @param selector - A `selector` to search for element to click. If there are
* multiple elements satisfying the `selector`, the first will be clicked
@ -3193,10 +3248,12 @@ export class Page extends EventEmitter {
* throws an error.
*
* @example
*
* ```ts
* page.select('select#colors', 'blue'); // single selection
* page.select('select#colors', 'red', 'green', 'blue'); // multiple selections
* ```
*
* @param selector - A
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | Selector}
* to query the page for
@ -3234,12 +3291,14 @@ export class Page extends EventEmitter {
*
* To press a special key, like `Control` or `ArrowDown`, use {@link Keyboard.press}.
* @example
*
* ```ts
* await page.type('#mytextarea', 'Hello');
* // Types instantly
* await page.type('#mytextarea', 'World', { delay: 100 });
* await page.type('#mytextarea', 'World', {delay: 100});
* // Types slower, like a user
* ```
*
* @param selector - A
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
* of an element to type into. If there are multiple elements satisfying the
@ -3288,6 +3347,7 @@ export class Page extends EventEmitter {
* function will throw.
*
* This method works across navigations:
*
* ```ts
* const puppeteer = require('puppeteer');
* (async () => {
@ -3307,6 +3367,7 @@ export class Page extends EventEmitter {
* await browser.close();
* })();
* ```
*
* @param selector - A
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
* of an element to wait for
@ -3343,6 +3404,7 @@ export class Page extends EventEmitter {
* function will throw.
*
* This method works across navigation
*
* ```ts
* const puppeteer = require('puppeteer');
* (async () => {
@ -3362,6 +3424,7 @@ export class Page extends EventEmitter {
* await browser.close();
* })();
* ```
*
* @param xpath - A
* {@link https://developer.mozilla.org/en-US/docs/Web/XPath | xpath} of an
* element to wait for
@ -3407,7 +3470,7 @@ export class Page extends EventEmitter {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* const watchDog = page.waitForFunction('window.innerWidth < 100');
* await page.setViewport({ width: 50, height: 50 });
* await page.setViewport({width: 50, height: 50});
* await watchDog;
* await browser.close();
* })();
@ -3416,10 +3479,11 @@ export class Page extends EventEmitter {
* @example
* To pass arguments from node.js to the predicate of
* {@link Page.waitForFunction} function:
*
* ```ts
* const selector = '.foo';
* await page.waitForFunction(
* (selector) => !!document.querySelector(selector),
* selector => !!document.querySelector(selector),
* {},
* selector
* );
@ -3427,10 +3491,11 @@ export class Page extends EventEmitter {
*
* @example
* The predicate of {@link Page.waitForFunction} can be asynchronous too:
*
* ```ts
* const username = 'github-username';
* await page.waitForFunction(
* async (username) => {
* async username => {
* const githubResponse = await fetch(
* `https://api.github.com/users/${username}`
* );
@ -3449,6 +3514,7 @@ export class Page extends EventEmitter {
*
* @param pageFunction - Function to be evaluated in browser context
* @param options - Optional waiting parameters
*
* - `polling` - An interval at which the `pageFunction` is executed, defaults
* to `raf`. If `polling` is a number, then it is treated as an interval in
* milliseconds at which the function would be executed. If polling is a

View File

@ -81,8 +81,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { devices } from 'puppeteer';
* import {devices} from 'puppeteer';
* ```
*/
get devices(): typeof devices {
@ -92,8 +93,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { errors } from 'puppeteer';
* import {errors} from 'puppeteer';
* ```
*/
get errors(): typeof errors {
@ -103,8 +105,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { networkConditions } from 'puppeteer';
* import {networkConditions} from 'puppeteer';
* ```
*/
get networkConditions(): typeof networkConditions {
@ -114,8 +117,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { registerCustomQueryHandler } from 'puppeteer';
* import {registerCustomQueryHandler} from 'puppeteer';
* ```
*/
registerCustomQueryHandler(
@ -128,8 +132,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { unregisterCustomQueryHandler } from 'puppeteer';
* import {unregisterCustomQueryHandler} from 'puppeteer';
* ```
*/
unregisterCustomQueryHandler(name: string): void {
@ -139,8 +144,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { customQueryHandlerNames } from 'puppeteer';
* import {customQueryHandlerNames} from 'puppeteer';
* ```
*/
customQueryHandlerNames(): string[] {
@ -150,8 +156,9 @@ export class Puppeteer {
/**
* @deprecated Import directly puppeteer.
* @example
*
* ```ts
* import { clearCustomQueryHandlers } from 'puppeteer';
* import {clearCustomQueryHandlers} from 'puppeteer';
* ```
*/
clearCustomQueryHandlers(): void {

View File

@ -261,6 +261,7 @@ const QUERY_HANDLERS = new Map<string, RegisteredQueryHandler>();
* allowed to consist of lower- and upper case latin letters.
*
* @example
*
* ```
* puppeteer.registerCustomQueryHandler('text', { });
* const aHandle = await page.$('text/…');

View File

@ -37,6 +37,7 @@ export interface TracingOptions {
* which can be opened in Chrome DevTools or {@link https://chromedevtools.github.io/timeline-viewer/ | timeline viewer}.
*
* @example
*
* ```ts
* await page.tracing.start({path: 'trace.json'});
* await page.goto('https://www.google.com');

View File

@ -49,9 +49,14 @@ type JSHandleFactory = (obj: Protocol.Runtime.RemoteObject) => JSHandle;
* object to signal the worker lifecycle.
*
* @example
*
* ```ts
* page.on('workercreated', worker => console.log('Worker created: ' + worker.url()));
* page.on('workerdestroyed', worker => console.log('Worker destroyed: ' + worker.url()));
* page.on('workercreated', worker =>
* console.log('Worker created: ' + worker.url())
* );
* page.on('workerdestroyed', worker =>
* console.log('Worker destroyed: ' + worker.url())
* );
*
* console.log('Current workers:');
* for (const worker of page.workers()) {

View File

@ -183,7 +183,9 @@ export interface BrowserFetcherRevisionInfo {
* ```ts
* const browserFetcher = puppeteer.createBrowserFetcher();
* const revisionInfo = await browserFetcher.download('533271');
* const browser = await puppeteer.launch({executablePath: revisionInfo.executablePath})
* const browser = await puppeteer.launch({
* executablePath: revisionInfo.executablePath,
* });
* ```
*
* **NOTE** BrowserFetcher is not designed to work concurrently with other

View File

@ -54,6 +54,7 @@ export interface PuppeteerLaunchOptions
*
* @example
* The following is a typical example of using Puppeteer to drive automation:
*
* ```ts
* const puppeteer = require('puppeteer');
*
@ -132,9 +133,10 @@ export class PuppeteerNode extends Puppeteer {
*
* @example
* You can use `ignoreDefaultArgs` to filter out `--mute-audio` from default arguments:
*
* ```ts
* const browser = await puppeteer.launch({
* ignoreDefaultArgs: ['--mute-audio']
* ignoreDefaultArgs: ['--mute-audio'],
* });
* ```
*

View File

@ -481,18 +481,19 @@ describeChromeOnly('NetworkManager', () => {
* This sequence was taken from an actual CDP session produced by the following
* test script:
*
* const browser = await puppeteer.launch(\{ headless: false \});
* ```ts
* const browser = await puppeteer.launch({headless: false});
* const page = await browser.newPage();
* await page.setCacheEnabled(false);
*
* await page.setRequestInterception(true)
* page.on('request', (interceptedRequest) =\> \{
* await page.setRequestInterception(true);
* page.on('request', interceptedRequest => {
* interceptedRequest.continue();
* \});
* });
*
* await page.goto('https://www.google.com');
* await browser.close();
*
* ```
*/
mockCDPSession.emit('Network.requestWillBeSent', {
requestId: '11ACE9783588040D644B905E8B55285B',

View File

@ -392,6 +392,7 @@ export class MarkdownDocumenter {
pageContent;
pageContent = pageContent.replace('##', '#');
pageContent = pageContent.replace(/<!-- -->/g, '');
pageContent = pageContent.replace(/\\\*\\\*/g, '**');
pageContent = pageContent.replace(/<b>|<\/b>/g, '**');
FileSystem.writeFile(filename, pageContent, {
convertLineEndings: this._documenterConfig

3763
website/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,17 +15,17 @@
"archive": "node archive.js"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.21",
"@docusaurus/preset-classic": "2.0.0-beta.21",
"@easyops-cn/docusaurus-search-local": "^0.28.0",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.1.1",
"prism-react-renderer": "^1.3.3",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"@docusaurus/core": "2.0.1",
"@docusaurus/preset-classic": "2.0.1",
"@easyops-cn/docusaurus-search-local": "0.26.1",
"@mdx-js/react": "1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "1.3.5",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-beta.21"
"@docusaurus/module-type-aliases": "2.0.1"
},
"browserslist": {
"production": [