DEV Community

Cover image for My journey developing the Github Action to Jazz up the code blocks in issues.
Mithun Kamath
Mithun Kamath

Posted on

My journey developing the Github Action to Jazz up the code blocks in issues.

Follow up of my submission to the #ActionsHackathon that you can find below:

My Github Action takes fenced code blocks in the issues and generates beautiful images for them using Carbon and replaces the code block to display the image instead. Why? Because (A) it looks slick, (B) It allows formatting the code and styling the syntax using guidelines you chose and (C) it makes it easy to read the code on mobile devices since one no longer has to scroll but only zoom.

Here's a document of my project journey - from how I started to the problems I encountered along the way and how I managed to resolved them to end up with a published version:

  • I started off by first going through Github Actions' awesome tutorial on how to create an Action. I know Nodejs and thus felt right at home taking the Javascript based Actions approach.
  • After that, I started off my exploring whether Carbon had any APIs. Could not find anything official but a search through their issue trackers led me to Carbonara, which allowed calling their service to generate the images

Carbonara build

API for carbon.

Getting started

Send POST https://carbonara.solopov.dev/api/cook to take an image of code snippet.

How it works

  • Puppeteer visit https://carbon.now.sh.
  • Mapping all params in properly URL params.
  • Taking a screenshot of the editor.

POST /api/cook

Body is JSON or multipart with next params:

parameter default type description
code (required) string code snippet
backgroundColor "rgba(171, 184, 195, 1)" string hex or rgba color
dropShadow true boolean turn on/off shadow
dropShadowBlurRadius "68px" string shadow blur radius
dropShadowOffsetY "20px" string shadow offset y
exportSize "2x" string resolution of exported image, e.g. 1x, 3x
fontCustom "" string custom woff font's contents, encoded in base64
fontSize "14px" string font size
fontFamily "Hack" string font family, e.g. JetBrains Mono, Fira Code. See all names in carbon exported config.
firstLineNumber 1 number first line number
language "auto" string programing language for properly highlighting. See name in carbon exported config
  • That was my first step - to generate the images from the code blocks. Having extracted the code block using a markdown parser library, I used the Carbonara API to generate the image. I first tested it locally and then used debug logs to verify that it indeed was generated in Github.
  • Having confirmed that, I moved to the next step - storing the image. I could not find any Github API to upload images / files to (the ones where we can upload within the issue itself) so had to resort to a third party API - Imgur in my case. I was familiar with Imgur and their API documentation was easy to follow so settled with that as my image host.
  • Finally I brought the two together: Generating the image and then hosting it on Imgur.

Comment for #1

Moment of truth.... Added the final bit - of updating the comment with the image and removing the code block... Let's see if this works now...

  • Now that I had the bare minimum completed, I decided to focus on improving it. Using Prettier came to mind. Wouldn't it be better if the code was formatted too, to make it easier to read and remove the responsibility of readability from the author? I quickly explored their documentation to determine how to use it programmatically and integrated it into my Action.
  • But Alas! Looks like I broke something. It did not generate the image. The logs also did not throw up anything promising. At first I assumed I had not integrated Prettier correctly. But that did not throw up anything promising. Frustrated at not being able to determine what caused the failure I traced my steps back and figured out that, during the download of the generated image and subsequent upload, I might not have coded it properly. If the image had a larger size, it would end up with a partial download and that might have contributed to my failure earlier.

Actually, I believe the previously accepted answer has some flaws, as it will not handle the writestream properly, so if you call "then()" after Axios has given you the response, you will end up having a partially downloaded file.

This is a more appropriate solution when downloading slightly larger files:

  • I corrected my code to correctly download the image in full and tried again. Sweet! It worked. That indeed was the cause of the earlier failure.
  • Onwards! I then decided to test my inputs - that allowed the user to specify the configurations for Prettier and Carbon. They worked well.
  • I then came across a scenario where Carbon had not styled the code properly. It failed midway and assumed everything to be a string after a certain line, and styled it as such. That made me realize that there could be a possibility that the Action may fail, and on such a occasion, losing the original code block might make matters worse. Thus, I decided to add that original source code into the issue after the generated image, but as a collapsed element.
  • I experimented with multiple markdown formats before settling on one that looked good.

Comment for #1

trying again...


View raw code
function HelloWorld({greeting = "hello", greeted = '"World"', silent = false, onMouseOver,}) {

  if(!greeting){return null};

     // TODO: Don't use random in render
  let num = Math.floor (Math.random() * 1E+7).toString().replace(/\.\d+/ig, "")

  return <div className='HelloWorld' title={`You are visitor number ${ num }`} onMouseOver={onMouseOver}>

    <strong>{ greeting.slice( 0, 1 ).toUpperCase() + greeting.slice(1).toLowerCase() }</strong>
    {greeting.endsWith(",") ? " " : <span style={{color: '\grey'}}>", "</span> }
    <em>
    { greeted }
    </em>
    { (silent)
      ? "."
      : "!"}

    </div>;

}
Enter fullscreen mode Exit fullscreen mode

outside text

  • All is well! I finally ended up doing some housekeeping - cleaning up my code, renaming my Action, adding a README etc and finally published my Action to the marketplace

You can actually see, step by step, how I arrived at the final version of my Action by checking this Github issue out. Every time I added significant code, I would test my Action out.

My test issue #1

Test issue to test my github action that will convert code snippets to beautiful images using Carbon.

const test = require('my-test-module')

console.log('Testing my stuff')
Enter fullscreen mode Exit fullscreen mode

References

Top comments (0)