Hugo Shortcodes for Coding Blogs
Published August 23, 2022
As I've been diving deep into PyScript the past couple months, I've developed a handful of shortcodes for Hugo that make it quicker and easier to display code snippets on the page in a nicely formatted way.
We'll use the following Python code as the source to be formatted. The code below is displayed by simply wrapped it in a pair of <pre></pre>
tags:
class hello_sayer: def __init__(self, greeting = "Hello"): self.greeting = greeting def say_hello(self, name): print(f"{self.greeting}, {name}!") if __name__ == "__main__": h = hello_sayer("Good morning") h.say_hello("Jeff")
This really isn't a bad place to start, but now let's make it better.
All of the following assumes the monokai syntax highlighting theme and use of the tailwind css framework. The custom css-classes used on this page are included at the end.
Built-in {{< highlight >}}
We can use Hugo's built-in {{< highlight >}}
shortcode to highlight our code. This works fairly-well for simple code examples that you're copying and pasting into the document - it's also the default behavior if you're relyingon Markdown code fences to do highlighting for you.
Code
{{ highlight python }} class hello_sayer: def __init__(self, greeting = "Hello"): self.greeting = greeting def say_hello(self, name): print(f"{self.greeting}, {name}!") if __name__ == "__main__": h = hello_sayer("Good morning") h.say_hello("Jeff") {{ /highlight }}
Result
|
|
Import Code with loadcode
The first and simplest shortcode I wrote I call loadcode
, which simply takes the contents of an external file and drops it into the current file. The source is:
layouts/shortcodes/loadcode.html
|
|
If we move our "hello_saver" code into a separate file called hellosayer.py
, we can use loadcode
to dynamically load the text into our page. This allows for using an external code editor to work on the code itself (with autocompletion, linting etc) while keeping the display correct on the page.
Code
{{< highlight python >}} {{< loadcode "post/Cloud-Resume-Challenge-Shortcodes/hellosayer.py" >}} {{< /highlight >}}
Result
|
|
Pleasing Code Displays with {{< showcode >}}
Of course when writing about code, it's nice for me to have a fairly standard format that code blocks are displayed in, including the title of the included file. The showcode
shortcode accomplishes this: it adds a nicely beveled header tag to the top of the code block, and ensures that if the code is over 20 lines, we prevent it from getting any longer and add a scrollbar. The second and third arguments to showcode
are the language to try to highlight and the highlight options:
layouts/shortcodes/showcode.html
|
|
Applying this to our hellosayer.py
example, we get:
Code
{{< showcode "post/Cloud-Resume-Challenge-Shortcodes/hellosayer.py" "python" >}}
Result
hellosayer.py
|
|
Displaying and Running PyScript Code with {{< showandrun >}}
For an upcoming post about integrating the Rich terminal formatting library with PyScript, I'd like to be able to run a piece of Python code in PyScript on the page and display its source code adjacent to it. For this, I use the showandrun
shortcode:
showandrun
creates a div which displays the source much like showcode
does; however, for my purposes, since it's intended specifically to run Python code and be formatted a specific way, the language is hardcoded to "python3" and the options are not passed from the shortcode.
The lengthy tailwind class list in the first div ensures that the code and results live side-by-side on large screens, but get stacked one-over-the-other on smaller/mobile screens. We also accept a "flip" parameter which swaps the placement of the code and results, if desired.
layouts/shortcodes/shownadrun.html
|
|
The result, when applied to hellosayer.py
, is:
Code
{{< showandrun file="post/Cloud-Resume-Challenge-Shortcodes/hellosayer.py" direction="flip" >}}
Result
hellosayer.py
|
|
CSS Classes
Many of the examples above make use of a couple of 'css-classes' in the tailwind style that I've defined for ease of use. Their definitions (in both tailwind classes and raw css) are:
/* in tailwind styles: */
.code-title {
@apply table-cell px-6 py-1 font-semibold leading-tight text-center text-white rounded-t-xl;
background-color: #f0f3f3;
}
/* in css: */
.code-title {
display: table-cell;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 1.5rem;
padding-right: 1.5rem;
color: #ffffff;
font-weight: 600;
line-height: 1.25;
text-align: center;
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
background-color: #f0f3f3;
}
/* in tailwind styles: */
.post-img-caption {
@apply w-auto m-auto italic text-center;
}
/* in css: */
.post-img-caption {
font-style: italic;
text-align: center;
width: auto;
}