SHARE
TWEET

Untitled

a guest Aug 19th, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const url = process.argv[2];
  2. if (!url) {
  3.   console.log(`Missing a url to analyze.`);
  4.   process.exit(1);
  5. }
  6. const puppeteer = require('puppeteer');
  7. puppeteer.launch().then(async browser => {
  8.   const page = await browser.newPage();
  9.   await page.goto(url);
  10.   const client = await page.target().createCDPSession();
  11.  
  12.   // go fullpage
  13.   const metrics = await client.send('Page.getLayoutMetrics');
  14.   const width = Math.ceil(metrics.contentSize.width);
  15.   const height = Math.ceil(metrics.contentSize.height);
  16.   await page.setViewport({
  17.     width, height
  18.   });
  19.   const screenshot = await page.screenshot({encoding: 'base64'});
  20.  
  21.  
  22.   await page.exposeFunction('sendTab', () => page.keyboard.press('Tab'));
  23.   const rects = await page.evaluate(async () => {
  24.  
  25.     const visited = new Set();
  26.     const blacklist = new Set([document.body, document.documentElement]);
  27.     /** @type {DOMRect[]} */
  28.     const rects = [];
  29.     while (true) {
  30.       const element = deepActiveElement();
  31.       if (!element || visited.has(element))
  32.         break;
  33.       visited.add(element);
  34.       if (!blacklist.has(element))
  35.         rects.push(element.getBoundingClientRect().toJSON());
  36.       await sendTab();
  37.     }
  38.  
  39.     return rects;
  40.  
  41.     function deepActiveElement() {
  42.       let activeElement = document.activeElement;
  43.       while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
  44.         activeElement = activeElement.shadowRoot.activeElement;
  45.       return activeElement;
  46.     }
  47.   });
  48.  
  49.   let prev = rects[rects.length - 1];
  50.   for (const rect of rects) {
  51.     rect.bad = !isOk(prev, rect);
  52.     prev = rect;
  53.   }
  54.  
  55.   function isOk(from, to) {
  56.     // dont care if its the same
  57.     // if (from.top === to.top && from.bottom === to.bottom && from.left === to.left && from.right === to.right)
  58.     //   return true;
  59.     // if we collide just say its ok
  60.     if (to.top < from.bottom && to.left < from.right && from.top < to.bottom && from.left < to.right)
  61.       return true;
  62.     // if we go down its ok
  63.     if (from.bottom < to.bottom || from.top <  to.top)
  64.       return true;
  65.     // if we go right its ok
  66.     if (from.left < to.left || from.right < to.right)
  67.       return true;
  68.     return false;
  69.   }
  70.  
  71.   // draw it on a canvas
  72.   await page.goto('about:blank');
  73.   const canvas = await page.evaluateHandle(async (rects, screenshot) => {
  74.     document.body.style.margin = '0';
  75.     const canvas = document.createElement('canvas');
  76.     const image = new Image();
  77.     await new Promise(x => {
  78.       image.src = 'data:image/png;base64,' + screenshot;
  79.       image.onload = x;
  80.     });
  81.     canvas.width = image.width;
  82.     canvas.height = image.height;
  83.     document.body.appendChild(canvas);
  84.     const ctx = canvas.getContext('2d');
  85.     ctx.drawImage(image, 0, 0);
  86.  
  87.  
  88.     ctx.lineWidth = 2;
  89.     ctx.beginPath();
  90.     let count = 0;
  91.     for (const rect of rects) {
  92.       const center = {x: rect.x + rect.width/2, y: rect.y + rect.height/2};
  93.       if (count === 0)
  94.         ctx.moveTo(center.x, center.y);
  95.       else
  96.         ctx.lineTo(center.x, center.y);
  97.  
  98.       ctx.fillStyle = 'rgba(255,128,0,0.2)';
  99.       ctx.strokeStyle = 'rgba(255,128,0,0.7)';
  100.       if (rect.bad) {
  101.         ctx.fillStyle = 'rgba(255,0,0,0.2)';
  102.         ctx.strokeStyle = 'rgba(255,0,0,0.7)';
  103.       }
  104.       ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
  105.       ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
  106.       count++;
  107.       ctx.fillStyle = 'rgba(255,255,255,0.5)';
  108.       ctx.strokeStyle = 'rgba(0,0,0,0.5)';
  109.       ctx.font = '40px sans-serif';
  110.       ctx.strokeText(count, center.x - ctx.measureText(count).width/2, center.y + 10);
  111.       ctx.fillText(count, center.x - ctx.measureText(count).width/2, center.y + 10);
  112.     }
  113.  
  114.     ctx.setLineDash([2, 2]);
  115.     ctx.strokeStyle = 'rgba(255,0,0,0.5)';
  116.     ctx.stroke();
  117.  
  118.     return canvas;
  119.   }, rects, screenshot);
  120.  
  121.   await canvas.screenshot({path: 'output.png'});
  122.  
  123.   await browser.close();
  124.  
  125.  
  126. }).catch(e => {
  127.   console.error(e)
  128.   process.exit(1);
  129. });
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top