mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: remove doclint generate_types code (#5932)
This script generated an `index.d.ts` file but that file was never commited to git nor included in Puppeteer when we ship. As of right now people who want TS types can install from the DefinitelyTyped repo and we are working on shipping types from Puppeteer itself. Therefore this script is not adding any value and can be removed.
This commit is contained in:
parent
7eab7f8dd9
commit
9737059400
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,5 @@ package-lock.json
|
||||
yarn.lock
|
||||
/node6
|
||||
/utils/browser/puppeteer-web.js
|
||||
/index.d.ts
|
||||
/lib
|
||||
test/coverage.json
|
||||
|
@ -67,7 +67,6 @@ jobs:
|
||||
- npm run test-install
|
||||
- npm run lint
|
||||
- npm run test-doclint
|
||||
- npm run test-types
|
||||
|
||||
# Runs unit tests on Linux + Firefox
|
||||
- node_js: "10.19.0"
|
||||
|
@ -29,7 +29,6 @@
|
||||
"doc": "node utils/doclint/cli.js",
|
||||
"tsc": "tsc --version && tsc -p . && cp src/protocol.d.ts lib/",
|
||||
"apply-next-version": "node utils/apply_next_version.js",
|
||||
"test-types": "node utils/doclint/generate_types && tsc --version && tsc -p utils/doclint/generate_types/test/",
|
||||
"update-protocol-d-ts": "node utils/protocol-types-generator update",
|
||||
"compare-protocol-d-ts": "node utils/protocol-types-generator compare",
|
||||
"test-install": "scripts/test-install.sh"
|
||||
|
@ -1,307 +0,0 @@
|
||||
const path = require('path');
|
||||
const Source = require('../Source');
|
||||
const puppeteer = require('../../..');
|
||||
const PROJECT_DIR = path.join(__dirname, '..', '..', '..');
|
||||
const fs = require('fs');
|
||||
const objectDefinitions = [];
|
||||
(async function () {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = (await browser.pages())[0];
|
||||
const api = await Source.readFile(path.join(PROJECT_DIR, 'docs', 'api.md'));
|
||||
const { documentation } = await require('../check_public_api/MDBuilder')(
|
||||
page,
|
||||
[api]
|
||||
);
|
||||
await browser.close();
|
||||
const classes = documentation.classesArray.slice(1);
|
||||
const root = documentation.classesArray[0];
|
||||
const output = `// This file is generated by ${__filename.substring(
|
||||
path.join(__dirname, '..', '..').length
|
||||
)}
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
/**
|
||||
* Can be converted to JSON
|
||||
*/
|
||||
interface Serializable {}
|
||||
interface ConnectionTransport {}
|
||||
|
||||
${root.methodsArray
|
||||
.map(
|
||||
(method) => `
|
||||
${memberJSDOC(method, '')}export function ${method.name}${argsFromMember(
|
||||
method
|
||||
)} : ${typeToString(method.type, method.name)};
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
${root.propertiesArray
|
||||
.map(
|
||||
(property) => `
|
||||
${memberJSDOC(property, '')}export const ${property.name}${argsFromMember(
|
||||
property
|
||||
)} : ${typeToString(property.type, property.name)};
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
${classes.map((classDesc) => classToString(classDesc)).join('\n')}
|
||||
${objectDefinitionsToString()}
|
||||
`;
|
||||
fs.writeFileSync(path.join(PROJECT_DIR, 'index.d.ts'), output, 'utf8');
|
||||
})();
|
||||
|
||||
function objectDefinitionsToString() {
|
||||
let definition;
|
||||
const parts = [];
|
||||
while ((definition = objectDefinitions.pop())) {
|
||||
const { name, properties } = definition;
|
||||
parts.push(`interface ${name} {`);
|
||||
parts.push(
|
||||
properties
|
||||
.map(
|
||||
(member) =>
|
||||
` ${memberJSDOC(member, ' ')}${nameForProperty(
|
||||
member
|
||||
)}${argsFromMember(member, name)}: ${typeToString(
|
||||
member.type,
|
||||
name,
|
||||
member.name
|
||||
)};`
|
||||
)
|
||||
.join('\n\n')
|
||||
);
|
||||
parts.push('}\n');
|
||||
}
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
||||
function nameForProperty(member) {
|
||||
return member.required || member.name.startsWith('...')
|
||||
? member.name
|
||||
: member.name + '?';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./check_public_api/Documentation').Class} classDesc
|
||||
*/
|
||||
function classToString(classDesc) {
|
||||
const parts = [];
|
||||
if (classDesc.comment) {
|
||||
parts.push(`/**
|
||||
* ${classDesc.comment.split('\n').join('\n * ')}
|
||||
*/`);
|
||||
}
|
||||
parts.push(
|
||||
`export interface ${classDesc.name} ${
|
||||
classDesc.extends ? `extends ${classDesc.extends} ` : ''
|
||||
}{`
|
||||
);
|
||||
for (const method of ['on', 'once', 'addListener']) {
|
||||
for (const [eventName, value] of classDesc.events) {
|
||||
if (value.comment) {
|
||||
parts.push(' /**');
|
||||
parts.push(...value.comment.split('\n').map((line) => ' * ' + line));
|
||||
parts.push(' */');
|
||||
}
|
||||
parts.push(
|
||||
` ${method}(event: '${eventName}', listener: (arg0 : ${typeToString(
|
||||
value && value.type,
|
||||
classDesc.name,
|
||||
eventName,
|
||||
'payload'
|
||||
)}) => void): this;\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
const members = classDesc.membersArray.filter(
|
||||
(member) => member.kind !== 'event'
|
||||
);
|
||||
parts.push(
|
||||
members
|
||||
.map(
|
||||
(member) =>
|
||||
` ${memberJSDOC(member, ' ')}${member.name}${argsFromMember(
|
||||
member,
|
||||
classDesc.name
|
||||
)}: ${typeToString(member.type, classDesc.name, member.name)};`
|
||||
)
|
||||
.join('\n\n')
|
||||
);
|
||||
parts.push('}\n');
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./check_public_api/Documentation').Type} type
|
||||
*/
|
||||
function typeToString(type, ...namespace) {
|
||||
/* A hack to special case TypeScript types that this type generator
|
||||
* does not understand / parse correctly.
|
||||
* Because the goal is to generate these types from the TypeScript
|
||||
* source, this parser won't be around for much longer so investing in
|
||||
* improving the parser's ability is not worth it.
|
||||
*/
|
||||
const specialCaseTypeMaps = new Map([
|
||||
[
|
||||
'"load"|"domcontentloaded"|"networkidle0"|"networkidle2"|Array',
|
||||
'"load"|"domcontentloaded"|"networkidle0"|"networkidle2"|Array<string>',
|
||||
],
|
||||
]);
|
||||
|
||||
if (!type) return 'void';
|
||||
|
||||
if (specialCaseTypeMaps.has(type.name))
|
||||
return specialCaseTypeMaps.get(type.name);
|
||||
|
||||
let typeString = stringifyType(parseType(type.name));
|
||||
for (let i = 0; i < type.properties.length; i++)
|
||||
typeString = typeString.replace('arg' + i, type.properties[i].name);
|
||||
if (type.properties.length && typeString.indexOf('Object') !== -1) {
|
||||
const name = namespace
|
||||
.map((n) => n[0].toUpperCase() + n.substring(1))
|
||||
.join('');
|
||||
typeString = typeString.replace('Object', name);
|
||||
objectDefinitions.push({ name, properties: type.properties });
|
||||
}
|
||||
return typeString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
*/
|
||||
function parseType(type) {
|
||||
type = type.trim();
|
||||
if (type.startsWith('?')) {
|
||||
const parsed = parseType(type.substring(1));
|
||||
parsed.nullable = true;
|
||||
return parsed;
|
||||
}
|
||||
if (type.startsWith('...'))
|
||||
return parseType('Array<' + type.substring(3) + '>');
|
||||
let name = type;
|
||||
let next = null;
|
||||
let template = null;
|
||||
let args = null;
|
||||
let retType = null;
|
||||
let firstTypeLength = type.length;
|
||||
for (let i = 0; i < type.length; i++) {
|
||||
if (type[i] === '<') {
|
||||
name = type.substring(0, i);
|
||||
const matching = matchingBracket(type.substring(i), '<', '>');
|
||||
template = parseType(type.substring(i + 1, i + matching - 1));
|
||||
firstTypeLength = i + matching;
|
||||
break;
|
||||
}
|
||||
if (type[i] === '(') {
|
||||
name = type.substring(0, i);
|
||||
const matching = matchingBracket(type.substring(i), '(', ')');
|
||||
args = parseType(type.substring(i + 1, i + matching - 1));
|
||||
i = i + matching;
|
||||
if (type[i] === ':') {
|
||||
retType = parseType(type.substring(i + 1));
|
||||
next = retType.next;
|
||||
retType.next = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type[i] === '|' || type[i] === ',') {
|
||||
name = type.substring(0, i);
|
||||
firstTypeLength = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let pipe = null;
|
||||
if (type[firstTypeLength] === '|')
|
||||
pipe = parseType(type.substring(firstTypeLength + 1));
|
||||
else if (type[firstTypeLength] === ',')
|
||||
next = parseType(type.substring(firstTypeLength + 1));
|
||||
if (name === 'Promise' && !template) template = parseType('void');
|
||||
return {
|
||||
name,
|
||||
args,
|
||||
retType,
|
||||
template,
|
||||
pipe,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
function stringifyType(parsedType) {
|
||||
if (!parsedType) return 'void';
|
||||
let out = parsedType.name;
|
||||
if (parsedType.args) {
|
||||
let args = parsedType.args;
|
||||
const stringArgs = [];
|
||||
while (args) {
|
||||
const arg = args;
|
||||
args = args.next;
|
||||
arg.next = null;
|
||||
stringArgs.push(stringifyType(arg));
|
||||
}
|
||||
out = `(${stringArgs
|
||||
.map((type, index) => `arg${index} : ${type}`)
|
||||
.join(', ')}, ...args: any[]) => ${stringifyType(parsedType.retType)}`;
|
||||
} else if (parsedType.name === 'function') {
|
||||
out = 'Function';
|
||||
}
|
||||
if (parsedType.nullable) out = 'null|' + out;
|
||||
if (parsedType.template)
|
||||
out += '<' + stringifyType(parsedType.template) + '>';
|
||||
if (parsedType.pipe) out += '|' + stringifyType(parsedType.pipe);
|
||||
if (parsedType.next) out += ', ' + stringifyType(parsedType.next);
|
||||
return out.trim();
|
||||
}
|
||||
|
||||
function matchingBracket(str, open, close) {
|
||||
let count = 1;
|
||||
let i = 1;
|
||||
for (; i < str.length && count; i++) {
|
||||
if (str[i] === open) count++;
|
||||
else if (str[i] === close) count--;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./check_public_api/Documentation').Member} member
|
||||
*/
|
||||
function argsFromMember(member, ...namespace) {
|
||||
if (member.kind === 'property') return '';
|
||||
return (
|
||||
'(' +
|
||||
member.argsArray
|
||||
.map(
|
||||
(arg) =>
|
||||
`${nameForProperty(arg)}: ${typeToString(
|
||||
arg.type,
|
||||
...namespace,
|
||||
member.name,
|
||||
'options'
|
||||
)}`
|
||||
)
|
||||
.join(', ') +
|
||||
')'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {import('./check_public_api/Documentation').Member} member
|
||||
*/
|
||||
function memberJSDOC(member, indent) {
|
||||
const lines = [];
|
||||
if (member.comment) lines.push(...member.comment.split('\n'));
|
||||
lines.push(
|
||||
...member.argsArray.map(
|
||||
(arg) =>
|
||||
`@param ${arg.name.replace(/\./g, '')} ${arg.comment.replace(
|
||||
'\n',
|
||||
' '
|
||||
)}`
|
||||
)
|
||||
);
|
||||
if (member.returnComment) lines.push(`@returns ${member.returnComment}`);
|
||||
if (!lines.length) return '';
|
||||
return `/**
|
||||
${indent} * ${lines.join('\n' + indent + ' * ')}
|
||||
${indent} */
|
||||
${indent}`;
|
||||
}
|
@ -1,283 +0,0 @@
|
||||
import * as puppeteer from "../../../../index";
|
||||
|
||||
// Examples taken from README
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
await page.screenshot({ path: "example.png" });
|
||||
|
||||
browser.close();
|
||||
})();
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://news.ycombinator.com", { waitUntil: "networkidle0" });
|
||||
await page.pdf({ path: "hn.pdf", format: "A4" });
|
||||
|
||||
browser.close();
|
||||
})();
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
|
||||
// Get the "viewport" of the page, as reported by the page.
|
||||
const dimensions = await page.evaluate(() => {
|
||||
return {
|
||||
width: document.documentElement.clientWidth,
|
||||
height: document.documentElement.clientHeight,
|
||||
deviceScaleFactor: window.devicePixelRatio
|
||||
};
|
||||
});
|
||||
|
||||
console.log("Dimensions:", dimensions);
|
||||
|
||||
browser.close();
|
||||
})();
|
||||
|
||||
// The following examples are taken from the docs itself
|
||||
puppeteer.launch().then(async browser => {
|
||||
const page = await browser.newPage();
|
||||
page.on("console", (...args: any[]) => {
|
||||
for (let i = 0; i < args.length; ++i) console.log(`${i}: ${args[i]}`);
|
||||
});
|
||||
page.evaluate(() => console.log(5, "hello", { foo: "bar" }));
|
||||
|
||||
const result = await page.evaluate(() => {
|
||||
return Promise.resolve(8 * 7);
|
||||
});
|
||||
console.log(await page.evaluate("1 + 2"));
|
||||
|
||||
const bodyHandle = await page.$("body");
|
||||
|
||||
// Typings for this are really difficult since they depend on internal state
|
||||
// of the page class.
|
||||
const html = await page.evaluate(
|
||||
(body: HTMLElement) => body.innerHTML,
|
||||
bodyHandle
|
||||
);
|
||||
});
|
||||
|
||||
import * as crypto from "crypto";
|
||||
import * as fs from "fs";
|
||||
|
||||
puppeteer.launch().then(async browser => {
|
||||
const page = await browser.newPage();
|
||||
page.on("console", console.log);
|
||||
await page.exposeFunction("md5", (text: string) =>
|
||||
crypto
|
||||
.createHash("md5")
|
||||
.update(text)
|
||||
.digest("hex")
|
||||
);
|
||||
await page.evaluate(async () => {
|
||||
// use window.md5 to compute hashes
|
||||
const myString = "PUPPETEER";
|
||||
const myHash = await (window as any).md5(myString);
|
||||
console.log(`md5 of ${myString} is ${myHash}`);
|
||||
});
|
||||
browser.close();
|
||||
|
||||
page.on("console", console.log);
|
||||
await page.exposeFunction("readfile", async (filePath: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(filePath, "utf8", (err, text) => {
|
||||
if (err) reject(err);
|
||||
else resolve(text);
|
||||
});
|
||||
});
|
||||
});
|
||||
await page.evaluate(async () => {
|
||||
// use window.readfile to read contents of a file
|
||||
const content = await (window as any).readfile("/etc/hosts");
|
||||
console.log(content);
|
||||
});
|
||||
|
||||
await page.emulateMedia("screen");
|
||||
await page.pdf({ path: "page.pdf" });
|
||||
|
||||
await page.setRequestInterception(true);
|
||||
page.on("request", interceptedRequest => {
|
||||
if (
|
||||
interceptedRequest.url().endsWith(".png") ||
|
||||
interceptedRequest.url().endsWith(".jpg")
|
||||
)
|
||||
interceptedRequest.abort();
|
||||
else interceptedRequest.continue();
|
||||
});
|
||||
|
||||
page.keyboard.type("Hello"); // Types instantly
|
||||
page.keyboard.type("World", { delay: 100 }); // Types slower, like a user
|
||||
|
||||
const watchDog = page.waitForFunction("window.innerWidth < 100");
|
||||
page.setViewport({ width: 50, height: 50 });
|
||||
await watchDog;
|
||||
|
||||
let currentURL: string;
|
||||
page
|
||||
.waitForSelector("img", { visible: true })
|
||||
.then(() => console.log("First URL with image: " + currentURL));
|
||||
for (currentURL of [
|
||||
"https://example.com",
|
||||
"https://google.com",
|
||||
"https://bbc.com"
|
||||
]) {
|
||||
await page.goto(currentURL);
|
||||
}
|
||||
|
||||
page.keyboard.type("Hello World!");
|
||||
page.keyboard.press("ArrowLeft");
|
||||
|
||||
page.keyboard.down("Shift");
|
||||
// tslint:disable-next-line prefer-for-of
|
||||
for (let i = 0; i < " World".length; i++) {
|
||||
page.keyboard.press("ArrowLeft");
|
||||
}
|
||||
page.keyboard.up("Shift");
|
||||
page.keyboard.press("Backspace");
|
||||
page.keyboard.sendCharacter("嗨");
|
||||
|
||||
await page.tracing.start({ path: "trace.json" });
|
||||
await page.goto("https://www.google.com");
|
||||
await page.tracing.stop();
|
||||
|
||||
page.on("dialog", async dialog => {
|
||||
console.log(dialog.message());
|
||||
await dialog.dismiss();
|
||||
browser.close();
|
||||
});
|
||||
|
||||
const inputElement = (await page.$("input[type=submit]"))!;
|
||||
await inputElement.click();
|
||||
});
|
||||
|
||||
// Example with launch options
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch({
|
||||
args: [
|
||||
'--no-sandbox',
|
||||
'--disable-setuid-sandbox',
|
||||
],
|
||||
handleSIGINT: true,
|
||||
handleSIGHUP: true,
|
||||
handleSIGTERM: true,
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
await page.screenshot({ path: "example.png" });
|
||||
|
||||
browser.close();
|
||||
})();
|
||||
|
||||
// Test v0.12 features
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch({
|
||||
devtools: true,
|
||||
env: {
|
||||
JEST_TEST: true
|
||||
}
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
const button = (await page.$("#myButton"))!;
|
||||
const div = (await page.$("#myDiv"))!;
|
||||
const input = (await page.$("#myInput"))!;
|
||||
|
||||
if (!button)
|
||||
throw new Error('Unable to select myButton');
|
||||
|
||||
if (!input)
|
||||
throw new Error('Unable to select myInput');
|
||||
|
||||
await page.addStyleTag({
|
||||
url: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
||||
});
|
||||
|
||||
console.log(page.url());
|
||||
|
||||
page.type("#myInput", "Hello World!");
|
||||
|
||||
page.on("console", (event: puppeteer.ConsoleMessage, ...args: any[]) => {
|
||||
console.log(event.text, event.type);
|
||||
for (let i = 0; i < args.length; ++i) console.log(`${i}: ${args[i]}`);
|
||||
});
|
||||
|
||||
await button.focus();
|
||||
await button.press("Enter");
|
||||
await button.screenshot({
|
||||
type: "jpeg",
|
||||
omitBackground: true,
|
||||
clip: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 200,
|
||||
height: 100
|
||||
}
|
||||
});
|
||||
console.log(button.toString());
|
||||
input.type("Hello World", { delay: 10 });
|
||||
|
||||
const buttonText = await (await button.getProperty('textContent')).jsonValue();
|
||||
|
||||
await page.deleteCookie(...await page.cookies());
|
||||
|
||||
const metrics = await page.metrics();
|
||||
console.log(metrics.Documents, metrics.Frames, metrics.JSEventListeners);
|
||||
|
||||
const navResponse = await page.waitForNavigation({
|
||||
timeout: 1000
|
||||
});
|
||||
console.log(navResponse.ok, navResponse.status, navResponse.url, navResponse.headers);
|
||||
|
||||
// evaluate example
|
||||
const bodyHandle = (await page.$('body'))!;
|
||||
const html = await page.evaluate((body : HTMLBodyElement) => body.innerHTML, bodyHandle);
|
||||
await bodyHandle.dispose();
|
||||
|
||||
// getProperties example
|
||||
const handle = await page.evaluateHandle(() => ({ window, document }));
|
||||
const properties = await handle.getProperties();
|
||||
const windowHandle = properties.get('window');
|
||||
const documentHandle = properties.get('document');
|
||||
await handle.dispose();
|
||||
|
||||
// queryObjects example
|
||||
// Create a Map object
|
||||
await page.evaluate(() => (window as any).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
|
||||
const mapInstances = await page.queryObjects(mapPrototype);
|
||||
// Count amount of map objects in heap
|
||||
const count = await page.evaluate((maps: Map<any, any>[]) => maps.length, mapInstances);
|
||||
await mapInstances.dispose();
|
||||
await mapPrototype.dispose();
|
||||
|
||||
// evaluateHandle example
|
||||
const aHandle = await page.evaluateHandle(() => document.body);
|
||||
const resultHandle = await page.evaluateHandle((body: Element) => body.innerHTML, aHandle);
|
||||
console.log(await resultHandle.jsonValue());
|
||||
await resultHandle.dispose();
|
||||
|
||||
browser.close();
|
||||
})();
|
||||
|
||||
// test $eval and $$eval
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
await page.$eval('#someElement', (element, text: string) => {
|
||||
return element.innerHTML = text;
|
||||
}, 'hey');
|
||||
|
||||
let elementText = await page.$$eval('.someClassName', (elements) => {
|
||||
console.log(elements.length);
|
||||
console.log(elements.map(x => x)[0].textContent);
|
||||
return elements[3].innerHTML;
|
||||
});
|
||||
|
||||
browser.close();
|
||||
})();
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"target": "es2015",
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [
|
||||
"test.ts",
|
||||
"../../../../index.d.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user