This week, I worked on my fifth pull request to Forem (the repository used to power DEV). The feature I decided to tackle was adding a βcopy to clipboardβ feature to code examples on blog posts.The pull request is still a work-in-progress, but I thought Iβd outline my thoughts and process of working on it so far. Open source is fun!
Where do I start?
The first thing I needed to figure out was how and where code blocks are rendered. I figured from that point, I would be able to insert the ability of being able to copy that code block.
I noticed that code blocks on posts all came with a highlight
class, so I spent a while trying to find where in the code this class was applied. I found some .scss
files where .highlight
was being referred to, but otherwise no luck.
This is usually the strategy I use when trying to find where code for a certain feature is located in the codebase. I inspect the page, and try to find a relevant class name or ID, or sometimes even a string of text on the page. I then try and search for this in the codebase. Iβd love to hear if you have any advice on better approaches.
I decided at this point to ask on the issue ticket for some help. Rhymes was super helpful (as always!) and pointed me in the right direction to markdown_parser.rb.
As it turns out, Forem makes use of a Ruby library called Rouge to convert markdown into HTML, and this library applies the highlight
class name. So it was definitely a bit of a red herring trying to find this in the codebase.
Making sense of the code
The markdown_parser.rb
file is responsible for creating the HTML that is used to render a blog post on DEV. Initially, trying to read this file felt very overwhelming. I think I went around in circles for a bit trying to figure out how this file worked, and how I would be able to add a βcopy codeβ feature to it.
Eventually, I decided to check out its test file, since tests will usually tell what sort of functionality is in the file that it is testing. I soon realised that the tests were testing a finalise
function, so I figured that would be a good place to start.
Looking at that function, I could see that after markdown had been converted to HTML with Rouge, some extra things were added to the HTML using functions like wrap_all_images_in_link
.I thought it sounded like a pretty good idea to do something similar, something along the lines of add_copy_icon_to_codeblocks
.
Using the clipboard web component
Rhymes had pointed out to me that web components were used in a couple of places already in Forem to allow copying text to a clipboard. Now, Iβm pretty new to web components so take everything I say below with a grain of salt!
Usage of the clipboard-copy web component looks something like this:
<clipboard-copy for="id-name">
Click to copy
</clipboard-copy>
<div id="id-name">Thing being copied</div>
When you click the copy button, it will look for an element with the ID that matches the argument that you passed in using for
. It will find that element, and copy the text inside of it.
Getting stuck
I fiddled for a while with trying to add this to each code block on the page. I eventually successfully added it to the page but clicking on the button to copy code did nothing!
This part of the process was super frustrating, and I didnβt really know what I had done wrong, or how to fix it. I also didnβt know anything about web components, so I thought maybe there was something I had done wrong there without realising.
To try and debug this problem, I wanted to try and get the web component working in any way I could. I tried adding it to the top of the blog post page (ignoring the code blocks for now) just to try and get it functional. No luck there either.I took a look at another usage of the web component, the βcopy link to articleβ feature (youβll be able to see it in the meatballs menu to the left of posts on DEV). I copy pasted that too to try and get things working.
A discovery?
After a while, I reached a realisation. The reason the βcopy link to articleβ feature works is that thereβs a separate file (initializeCommentDropdown.js) that adds the copy functionality like this:
clipboardCopyElement.addEventListener('click', copyText);
function copyText() {
// all the functionality of copying text
}
To me, it seems like the web component isnβt actually doing anything, and all the functionality for copying the code to a clipboard lives inside of this file.
I might be missing something completely obvious - let me know if you know whatβs happening!
By re-using this code, I manage to get the βcopy codeβ functionality working on my side.
Raising a WIP pull request
At this point, Iβm a little bit confused on the purpose of the web component, and I decided that before I go any further, Iβd raise a a WIP pull request to the Forem repository so that I can get some feedback on whether Iβm heading down the right path or not.
I was hoping to get most of this feature done, so itβs frustrating that I got stuck like this, and the web component is still a bit of a mystery to me. But Iβm glad I managed to at least get halfway towards a solution. Hopefully I get some more information on this soon!
Top comments (7)
This is an excellent post, because it's not just going through the motions of doing something, but explains how you worked through the problem and what lead you to your decisions.
Anyone who can google can slap code together and make it run. The ability to problem solve, or just figuring out how to get from point A to point B (or as close as you can to point B before asking for assistance) is arguably a much more valuable skill to have. There are sometimes when you can ask a million questions and there are times when you just have to "get it done".
Looking forward to more. Well done!
Thanks Jim!
Hi Emma, thanks a lot for your contribution and exploration. I tagged our resident frontend wizard @nicktyonline in the PR who might be more helpful than I can :)
Thank you again!
Thank you - you've always been super communicative and approachable on my PRs so far!
Great post the breakdown was very insightful.
Good Luck with it Emma πππ
By the way I am too in the way Making my first PR, asap Learn Ruby With great efforts π..
Ooh, good luck to you too!