Adding Markdown Support to a Static Site Generator
Leyang Yu
Posted on October 29, 2021
Docusaurus
This week in my open source development class, we learned about Docusaurus, which is a static site generator in React that creates static webpages from markdown files. Docusaurus has a lot of interesting features such as themes, plugins, configurable sidebar navigation, full markdown support, and more.
Setting up a Docusaurus project and deploying it to GitHub pages was a very simple process that can all be done from the command line. You can see the result here. I think it would be a great tool to use even for people who may not have a lot of development experience.
Adding Markdown Support to My SSG
For my own static site generator, Jellybean, one feature from Docusaurus that I wanted to implement was full markdown support. This is because my static site generator previously only had partial markdown support, which is not very user-friendly. Thankfully, there are a some great open-source libraries which can provide full markdown support and I decided to use markdown-it for my project.
Using markdown-it in my project was fairly straightforward. Before, I was splitting each file into strings by newline, using regex to detect markdown syntax, replacing the markdown syntax with HTML tags, and wrapping each non-heading line in a <p>
tag.
html.body = file
.split(/\r?\n\r?\n/)
.map((para) => {
if (para == html.title) {
`<h1>${para.replace(/\r?\n/, ' ')}</h1>\n`;
} else {
if (isTxt) {
return `<p>${para.replace(/\r?\n/, ' ')}</p>\n`;
} else {
let string = para
.replace(/^\s*#{1} (.*$)/, '<h1>$1</h1>')
.replace(/^\s*#{2} (.*$)/, '<h2>$1</h2>')
.replace(/^\s*#{3} (.*$)/, '<h3>$1</h3>')
.replace(/\`{1,}(.*?)\`{1,}/g, '<code>$1</code>')
.replace(/-{3,}/g, '<hr />')
return string.startsWith('<h')
? string + '\n'
: `<p>${string.replace(/\r?\n/, ' ')}</p>\n`;
}
}
})
.join('');
return html;
Following the markdown-it usage docs, I no longer had to split the file into individual lines as this was already done by markdown-it. Furthermore, I could easily render markdown as HTML:
const markdownit = require('markdown-it');
//
if (isTxt) {
//
} else {
md = new markdownit();
html.body = md.render((file.substring((html.title).length)).trim());
}
return html;
In addition to the changes above, I improved CSS styling for the generated pages, such as styling for tables and code blocks:
I used an interactive rebase to squash all my changes into one commit and rebased this with my main branch.
Next Steps
My prototype and initial goal was to have markdown support similar to what GitHub provides. Although I was able to mostly achieve this, there are still a number of next steps I need to take.
Issue 1
There is currently a bug where HTML in markdown files gets converted into plain text. In GitHub, markdown files can contain HTML tags, which get rendered as HTML. However, markdown-it converts angle brackets into <
and >
, which causes the HTML tags to be rendered as plain text. By allowing users to use both markdown syntax and HTML in their markdown files, this would provide users with more options for how to customize their files so this is one bug I hope to fix in the future.
Issue 2
Another feature that I hope to add is syntax highlighting for code blocks in markdown files. In this blog post, which was written in markdown, you can see that the blocks of code have syntax highlighting which makes it easier to read. markdown-it provides support for this feature, so I hope to add it to my project as well.
There are possibly other features such as Markdown Frontmatter support and others that could improve user experience even more.
Conclusion
Overall, it was really interesting to learn about Docusaurus and implement one of its features in my own project. I was also really interested in Docusaurus' themes and configurable sidebar, so I hope to have the chance to add similar features to my project in the future.
Posted on October 29, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.