DEV Community

Lanie Hei
Lanie Hei

Posted on

Build a Go Playground Custom Hugo Shortcode

Note: this article was originally published on my site.

When I started with Hugo, I began my blog with a prefabricated template. In my opinion, this is the best option if you want to start creating things to put on your site. Unfortunately for me, I still fell into this hole when I wanted to create a way for users to open my code up in the Go Playground and run it for themselves when I discovered the functionality wasn't prexisting in the built-in highlight shortcode.

I hoped this would be similar to how the Go By Example site implements theirs. After asking Go Playground if I could reference the playground on my site (they specifically tell you to ask on the site and please also do so if you want to use this for your own site), I went about hacking myself an addition to the already-present highlight shortcode. For those unfamiliar, the highlight shortcode provides syntax highlighting to Hugo sites in a variety of themes, a method to copy the code, as well as other features.

If I can be honest, the most challenging part about this was figuring out how to use CSS again, since it's been so long since I was involved with it beyond seeing if I could get past a paywall in the inspector tools. Given that I knew this to be the case, I started writing the shortcode that would allow me to ignore my shortcomings with CSS, and focus on my shortcomings with understanding how custom shortcodes are implemented.

The reason I wanted this to be a shortcode rather than a partial because the description of partial was exactly what I was looking for -- a small, reusable bit of code that lived inside of my content. I needed to insert it directly into the markdown file I was writing, because it needed the URL I would give it to tell it which Go Playground URL to redirect to. I created the shortcode under the /layouts/shortcodes path, and named it goplay.html because the task at least was evident.

In practice, the execution of the shortcode was simple.

<div class="run">
    <form action="http://play.golang.org/p/{{.Get "url"}}" target="_blank" >
    <input type="submit" value="Run" class="goplay-btn" />
    </form>
</div>
Enter fullscreen mode Exit fullscreen mode

However, if you don't understand shortcodes immediately, know that I was exactly there when starting this. Above, you can see that the second line is grabbing a string "url" with the built-in .Get function that comes along with Hugo templating. I can pass the URL into the markdown file using the following syntax: {{ "{{ goplay url=abcde " }}}}, where abcde is the end of the url that denotes a unique saved playground. I chose to use a form, rather than a button, because I didn't see a way for a button to reference a .URL and open a new tab right away. It's probably possible: this was just the way I knew how to do it. The target is set to "_blank" so that it opens in a new tab, rather than diverting from the current page.

You'll also notice that the class for the overarching div is "run", and the class for the type submit input is "goplay-btn". I created another file under static/css called goplay.css. I inserted the following into this file:

.run{
    background:#2c3e50;
    display: flex;
    justify-content: flex-end;
    padding-top: 7px;
    padding-bottom: 7px;
    padding-right: 7px;
}
Enter fullscreen mode Exit fullscreen mode

This is the parent container for my button, and will match the color of the highlight code for my specific theme (Dracula) while completely filling the space, as the built-in highlight shortcode does. I use the word "button" loosely here, as it's a form element, not a button element. The padding gives the internal child element a little bit of room so it's not smushed against the bottom-right corner. You'll also notice that I used flex-box.

.goplay-btn {
  bottom: 7px;
  right: 7px;
  border: 0;
  border-radius: 4px;
  padding: 1px;
  font-size: .75em;
  line-height: 1.8;
  background-color: #777;
  opacity: .6;
  min-width: 55px;
  text-align: center;
}

.goplay-btn:hover {
  opacity: .45;
}
Enter fullscreen mode Exit fullscreen mode

Above, the goplay-btn class is in charge of styling my actual button. I moved the internal text around a bit, and changed the background color to match the copy button in the hightlight shortcode. I also changed the opacity to match the other shortcode's. I was able to grab a few of the attributes, such as font-size from inspecting the copy button in hugo's highlight shortcode docs, since it's open source. I change the opacity on hover to mimic a button element's natural tendency to do so -- this is completely a hack.

.chroma { margin-bottom: 0px; }
Enter fullscreen mode Exit fullscreen mode

The final key that stumped me a bit is this piece of CSS that I added to the same goplay.css file. Previous to adding this, there was a very ugly space between the hightlight shortcode, and the custom shortcode, which was there automatically within my base theme's (Hermit) template. Because the extra space was caused by the highlight shortcode's parent container, I couldn't do anything to my custom shortcode to eliminate this extra space. By targeting the chroma class in this file, we'll be able to override the bottom margin, and successfully remove the space. The paragraphs in the markdown file seem to have their own spacing, so I haven't noticed any negative consequences to overriding this attribute on the chroma class, but there's probably a cleaner way to do this.

After this code is implemented, you'll be able to link out to the Go Playground by inserting {{ "{{ goplay url=abcde " }}}} into the markdown file directly under the closing tag for your highlight shortcode.

Below you can see the finished code!

snippet of code with "play" button present as example of finished code

This also happens to be my first contribution to the open source community! I've pushed a repo with all this code to my github profile, and you are free to use on your personal site.

Top comments (1)

Collapse
 
ggicci profile image
Ggicci

Hi @byelanie
I was looking for a solution to embed Go playground on my website and came across with this post. Unfortunately it seems not working any more. I'm very happy to let you know that I also invented one in my way. If you were interested in this and maybe someone were also looking for a solution and came here, I'd like to share: ggicci.me/goplay.