Home About Notes

Github copilot

Feb 27, 2023

Github copilot is generally available, so I decided to try it out.

For a test project i'm building a little react app for kanban cards. These cards have a QRCode, a title, subtitle and description. I want users to be able to download these cards so that they can be printed out and placed with the consumables they relate to.

To enable these cards to be printed, I need a way to convert a react component into a image and then download it. In principal I know this should be possible but I  have no idea of the exact API's I might need. So I start with this prompt:

// function to download the qr code

it then generates the following code line by line (side note, this line by line is the magic, I can review and correct as we are going, if it was to just spit out a full function like you see in screenshots, that is in my mind a lot harder to review. remember reviewing code is 2x harder than writing, so this while 'easier' is also much harder in my mind)

// function to download the qr code
function downloadQRCodeCanvas() {
  const canvas = document.querySelector('canvas') as HTMLCanvasElement;
  const pngUrl = canvas
    .toDataURL('image/png')
    .replace('image/png', 'image/octet-stream');
  let downloadLink = document.createElement('a');
  downloadLink.href = pngUrl;
  downloadLink.download = 'qrcode.png';
  document.body.appendChild(downloadLink);
  downloadLink.click();
  document.body.removeChild(downloadLink);
}

Ok so its selecting the canvas and converting that to a png url and creating a download link. All seems okish I guess. Problem is im not using a canvas for either the qrcode or react component. So I try again adding the word 'svg' as my qrcode is an svg element:

// function to download the svg qr code

It spits out this function:
// function to download the svg qr code
function downloadQRCode() {
  const svg = document.querySelector('svg') as SVGSVGElement;
  const svgData = new XMLSerializer().serializeToString(svg);
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const img = new Image();
  img.onload = function () {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx?.drawImage(img, 0, 0);
    const pngUrl = canvas
      .toDataURL('image/png')
      .replace('image/png', 'image/octet-stream');
    let downloadLink = document.createElement('a');
    downloadLink.href = pngUrl;
    downloadLink.download = 'qrcode.png';
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  };
  img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgData)));
}

Again selects the svg, converts it to a canvas, then draws in that canvas and downloads it. I had no idea if this was right, so I ran it. It actually worked, it downloaded my svg as a png. Brilliant.

But that wasn't the end goal. I wanted my react component to be downloaded with my styles. I did some googling and decide that this library would work and that I will try it. So I prompted:

// function to download react view as jpeg using html-to-image

And it gave me this:
// function to download react view as jpeg using html-to-image
function downloadQRCodeReact() {
  const node = document.querySelector('.card') as HTMLElement;
  toJpeg(node)
    .then(function (dataUrl) {
      var img = new Image();
      img.src = dataUrl;
      let downloadLink = document.createElement('a');
      downloadLink.href = img.src;
      downloadLink.download = 'qrcode.jpeg';
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);
    });
}

It picked up the right css class .card selected the right API toJpeg looks pretty much like the examples on the readme of html-to-image, but added the combination of downloading it unlike the readme of html-to-image which calls to add another lib called download.

Very impressed from this short experiment with it and will continue to explore how to leverage these tools.