Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const url = process.argv[2];
- if (!url) {
- console.log(`Missing a url to analyze.`);
- process.exit(1);
- }
- const puppeteer = require('puppeteer');
- puppeteer.launch().then(async browser => {
- const page = await browser.newPage();
- await page.goto(url);
- const client = await page.target().createCDPSession();
- // go fullpage
- const metrics = await client.send('Page.getLayoutMetrics');
- const width = Math.ceil(metrics.contentSize.width);
- const height = Math.ceil(metrics.contentSize.height);
- await page.setViewport({
- width, height
- });
- const screenshot = await page.screenshot({encoding: 'base64'});
- await page.exposeFunction('sendTab', () => page.keyboard.press('Tab'));
- const rects = await page.evaluate(async () => {
- const visited = new Set();
- const blacklist = new Set([document.body, document.documentElement]);
- /** @type {DOMRect[]} */
- const rects = [];
- while (true) {
- const element = deepActiveElement();
- if (!element || visited.has(element))
- break;
- visited.add(element);
- if (!blacklist.has(element))
- rects.push(element.getBoundingClientRect().toJSON());
- await sendTab();
- }
- return rects;
- function deepActiveElement() {
- let activeElement = document.activeElement;
- while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
- activeElement = activeElement.shadowRoot.activeElement;
- return activeElement;
- }
- });
- let prev = rects[rects.length - 1];
- for (const rect of rects) {
- rect.bad = !isOk(prev, rect);
- prev = rect;
- }
- function isOk(from, to) {
- // dont care if its the same
- // if (from.top === to.top && from.bottom === to.bottom && from.left === to.left && from.right === to.right)
- // return true;
- // if we collide just say its ok
- if (to.top < from.bottom && to.left < from.right && from.top < to.bottom && from.left < to.right)
- return true;
- // if we go down its ok
- if (from.bottom < to.bottom || from.top < to.top)
- return true;
- // if we go right its ok
- if (from.left < to.left || from.right < to.right)
- return true;
- return false;
- }
- // draw it on a canvas
- await page.goto('about:blank');
- const canvas = await page.evaluateHandle(async (rects, screenshot) => {
- document.body.style.margin = '0';
- const canvas = document.createElement('canvas');
- const image = new Image();
- await new Promise(x => {
- image.src = 'data:image/png;base64,' + screenshot;
- image.onload = x;
- });
- canvas.width = image.width;
- canvas.height = image.height;
- document.body.appendChild(canvas);
- const ctx = canvas.getContext('2d');
- ctx.drawImage(image, 0, 0);
- ctx.lineWidth = 2;
- ctx.beginPath();
- let count = 0;
- for (const rect of rects) {
- const center = {x: rect.x + rect.width/2, y: rect.y + rect.height/2};
- if (count === 0)
- ctx.moveTo(center.x, center.y);
- else
- ctx.lineTo(center.x, center.y);
- ctx.fillStyle = 'rgba(255,128,0,0.2)';
- ctx.strokeStyle = 'rgba(255,128,0,0.7)';
- if (rect.bad) {
- ctx.fillStyle = 'rgba(255,0,0,0.2)';
- ctx.strokeStyle = 'rgba(255,0,0,0.7)';
- }
- ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
- ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
- count++;
- ctx.fillStyle = 'rgba(255,255,255,0.5)';
- ctx.strokeStyle = 'rgba(0,0,0,0.5)';
- ctx.font = '40px sans-serif';
- ctx.strokeText(count, center.x - ctx.measureText(count).width/2, center.y + 10);
- ctx.fillText(count, center.x - ctx.measureText(count).width/2, center.y + 10);
- }
- ctx.setLineDash([2, 2]);
- ctx.strokeStyle = 'rgba(255,0,0,0.5)';
- ctx.stroke();
- return canvas;
- }, rects, screenshot);
- await canvas.screenshot({path: 'output.png'});
- await browser.close();
- }).catch(e => {
- console.error(e)
- process.exit(1);
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement