Micro.blog has recently enabled Hugo v0.158.0 for usage. The last version available to users was v0.117.0 and v0.140.0. And as Jason has pointed out on his blog, there are some big changes.
One of the changes of note was the inclusion of render hooks for callouts included in v0.132.0. This is coupled with the enhancements in v0.134 makes it more compatible with GitHub, Obsidian, and Typora.
The whole goal of this is to have markdown text like the following
> [!NOTE]
> Useful information that users should know, even when skimming content.
generate HTML and have the browser render into the following example
In case there is an error with processing the markdown, I’ve placed a static version of the HTML in this document below.
I wanted to implement this because I sometimes play around with Obsidian and I really enjoy Otávio’s plugin to publish to Micro.blog. With this, I can have the website follow the behavior of reading mode in Obsidian. I started writing this post in December of 2024. I ran into some issues along the way, but I kept coming back to this. At this point, some of the references are no longer available. My desire for writing in a way where I would use this functionality is no longer there.
But, it’s cool, and I know that there might be someone out there who can use this.
I set up a gallery of examples using the list of callouts from the Obsidian Callout Manager. You can look at the text used to make the examples to see if this is something that you want to incorporate into your writing.
I’ve tagged this particular release on GitHub so you can see exactly what I’m using at the time of this writing.
If you have any questions or suggestions, feel free to email me.
Resources
I’m leaning heavily on the resources that I’ve found on the internet. I want to take a moment to recognize their work and others can get it directly from the source.
- Nicholas Martignoni’s Hugo Notice
- This is a plugin that I saw a while ago and was thinking about putting into my theme before the official release of render hooks.
- Liu Jinyi
- This is where I got the final design for the admonitions from. I decided to make some changes so that it matches the style that I wanted to go for. At beginning of this project, the build system I was using did not allows for sass.
Creating the callout
When it comes to designing
, I like to take inspiration from what is already available. I spent a lot of time goofing off researching how other people have implemented this and tried static version of those in my theme to see what I liked and didn’t like. Sometimes this takes up a lot of time as I try to understand why the original authors make certain decisions. Is it a technical or design choice that makes someone use <blockquote> or <div> for the final product?
This article about pullquotes better articulates why I use <aside> instead of <blockquote>. I have seen people use <figure>, but choose not to because I feel that figures are an essential part of the document while <aside> is additive.
I also went with a <header> inside of the admonition in the hopes that I’ll better understand how the different pieces come together. In addition, I used the <h3> tag to meet up with the heading convention that I’ve been using. I see the callouts as section of the document that contains information
I placed the content in a <div> for logistics and styling.
Iconic Icons
For the <svg>, I took some time to understand how they work in HTML and Hugo. I was already in the process of adding SVG icons to the site to make it stand out more. SVG stands for Scalable Vector Graphics. They are text representation of a graphic that we can embed within the document for the browser to render.
These are some that popular sites where you can get SVGs.
- tabler icons
- When I started looking into adding icons, this was one of the first links that came into my search.
- font awesome
- This is where Roneo got his icons. It’s a great option that is used in a lot projects on the internet.
- Simple Icons
- Another good set of icons.
- Lucide
- These are the icons that GitHub uses.
- Iconify Design
- This is a nice directory of icons that show you a small preview of the style icon libraries.
If you use any of these options, I want to encourage you to make a donation so that they can continue with the cool stuff that they are providing.
I went with the tabler icons, because I felt that the rounder style matches the ascetic that I’m going for when I started the site.
I’m in the process of implementing icons within my markdown after reading an article about SVG imbeds1 but that’s for a future post.
If you are into reading more about SVGs, there is a free book on SVG that I’m thinking about adding to the list.
Static Structure
The resulting static HTML that I created to do my color styling looks similar to the following.
<aside class="admonition note">
<header class="admonition-header">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-note">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M13 20l7 -7" />
<path d="M13 20v-6a1 1 0 0 1 1 -1h6v-7a2 2 0 0 0 -2 -2h-12a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7" />
</svg>
<h3>Note</h3>
</header>
<div class="admonition-content">
Useful information that users should know, even when skimming content.
</div>
</aside>
Styles and colors
For the initial implementation, I wanted to get the 5 states defined in the GitHub documentation which are note, tip, important, warning, and caution. This took longer than it should because I was having trouble deciding on what icon I should use for note and important because of the different samples I was pulling from contradict.
I placed static copies of the HTML in a page with the first line changed to the corresponding type as the class.
For example, the class for tip would look like this:
<aside class="admonition tip">
I then created a separate CSS file and linked it in the site header. I’m hoping that it will make things easier to find and modify styles in the future2. Since I’m working from Jinyi’s code as my base, I start off with the basic admonition and a note.
|
|
- Line 2
- I define the default color for the admonitions to be the accent color of my site with a default value in case someone takes this file and attempts to use it by itself.
- Line 9-12
- I use the
--admonition-colorto set the borders appropriately. - Line 14
- I use a box-shadow to give the callout some depth.
|
|
- Line 7
- Defines the upper right hand corner to be rounded to fit within the containing admonition. I attempted to use
inheritbut it wasn’t working. - Line 8
- This is where the
magic
happens and we start seeing the Cascade portion of CSS. This makes the forefront/currentColor--admonition-color. This is used in fonts and any svgs that are in the header. - Line 10
- I didn’t want to define two colors and found this tip on stack overflow to do a transparency translation of it.
- Line 19-20
- These are there to make some adjustments for contrast and size.
After that, I add a little bit of styling for the contents.
.admonition-content {
padding: 0.5rem;
}
After that, we look at our base example.
Here it is without the rendering.
With this, I can change the color based off the alert.
.admonition.note {
--admonition-color: #096ae1;
}
If I want to have the same color for multiple alerts, I can add an extra line for it.
.admonition.danger,
.admonition.warning {
--admonition-color: orangered;
}
Implementing the Render Hook
I started with the example from the blockquote/alert documentation and I was really happy to know that it worked correctly by simply creating the file and putting the sample code in. Making the changes to the HTML tags was also pretty straight forward.
|
|
- Line 1-9
- Create a
dictionaryto match which image goes to a specific image. Jinyi used the icon set from font-awesome so the names are not an exact match. I started off with just the basics and addinfobecause I was working on this late at night and couldn’t remember if it wasinfoorimportantthat was part of the five initial alerts. - Line 12
- The render hook will parse the different blocks of text and will set a flag on whether this block is an alert or not.
- Line 14
- Look in the dictionary for the alert type that was given by the user. If the alert type isn’t there, it will use
infoas the default. I decided that if I don’t have an icon in mind, I want it to show up as information to be given to the user. - Line 15
- This specifies the path to the SVG that we’re going to use. I had attempted to use the method from Ronoe to load image from the assert directory but I didn’t understand the code at this point in time. I used a different variable for the file name because I didn’t want to confuse myself later on.
- Line 17
- Specify the alert type in the class list for the admonition to use the proper styling.
- Line 19-20
- Hugo loads the contents of the partial if it exist and puts it in the output. It’s a safe guard in case I add an image to the icons dictionary but don’t upload the file. In addition, there was a change to the templating system introduced in v0.146.0 that renamed
partialto_partial. Be aware of that when implementing this on your own. - Line 22
- Check if there is an alert title and place it in the heading on the following line.
- Line 25
- If the title isn’t there, we use the alert type for the heading. All the examples that I’ve seen also include the step of sending it through i18n for internationalization. One thing I noticed, is that it capitalized the alert properly before I created the associated translation file. I might just leave it that way because I’m currently the only one using this theme.
- Line 28
- This checks for the content of the alert and places it in a
<div>for the admonition. - Line 35
- If there isn’t an alert, text is processed as if it was a normal
<blockquote>element.
Further callout options
After the initial creation of the render hook, I took some time away from the project. Some of the people that create content that I enjoy use Obsidian on a regular basis for writing and the ever growing list of what that application can do. Someone pointed out that there is a Callout Manager and the default has more than the list that I originally created. Other tools also have a wider assortment. I added a couple more to the dictionary, but I noticed that this would get tedious to add keys that would go to the same value. For example, in my list info and important use the same image.
So, after a little bit of trial and error, I was able to put together the following code block
- Line 2
- Place the keys that I want to have the same image
- Line 3
- Tells go to loop through all the keys that are defined
- Line 5
- Creates a small dictionary with the key and the name of the image. Then it merges that dictionary with the icon dictionary and saves it.
I’m still a beginner at the go programming language and I don’t know if this is saving by value or reference. I also don’t know if this is more performant than having a longer dictionary with all the values. I’m hoping that the comments and this article helps me remember this the next time I want to add something.
Making it a little more accessible
During this development process, I noticed that one example would load the SVG and add aria-hidden="true" to make screen readers skip over the image without alternative text. I edited the SVG files that I use to have this additional line and played with the idea of adding aria-labelledby but I don’t have a way of reliably setting it and don’t know how this would improve the user experience.
The same example, also set the title, but I didn’t use this as this images are purely decorative. You can read this article about knowing the different use cases for aria visibility.
What’s the next step?
I feel the next step that I would like to pursue is to get get the colors to work better in the dark mode of my theme. I don’t feel that the contrast is good enough for warning and I’m thinking about moving to CSS colors such as blue or rebeccapurple instead of hexidecimal values. I’ve already done one like the following
.admonition.important {
--admonition-color: light-dark(rebeccapurple, mediumorchid);
}
I’d also like to adjust the alignment of the icons. I don’t know if this is because I took the examples from different icons that are sized differently or if having the icon outside of the <h3> is causing more issues than it’s worth.
As always, I appreciate any feed back and I hope this article finds you well.
-
By the time I got ready to publish this article, the site was no longer available. I’m hoping that it’s just a temporary shutdown until this person has the domain refreshed. ↩︎
-
I have had to stop myself a couple times from trying to find the best way to deliver the HTML/CSS for this feature. Should I have separate files with style rules that I might not use or put it inline and worry that I might have an article that use dozens of these things? I feel shipping is more important. ↩︎