Golang Markdown



Golang markdown parserFollow me on twitch!

Golang Markdown Table

In this post we’re going to have a look at how to create a simple Markdown powered blog with Go(lang) and gin. The blog will be able to look up a markdown file by title / filename, display a list of all blog posts, display a single blog post and give the user an error page when a link can not be found.

Golang Markdown

Requirements:

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. Blackfriday Blackfriday is a Markdown processor implemented in Go. It is paranoid about its input (so you can safely feed it user-supplied data), it is fast, it supports common extensions (tables, smart punctuation substitutions, etc.), and it is safe for all utf-8 (unicode) input. Use the container list module for a linked list. Benchmark container list against slices. My contribution to the increasing entropy, and eventual heat death of the universe.

  • You have Go installed
  • You have (very) basic terminal command experience

Kids', toddler, & baby clothes with Google designs sold by independent artists. Shop high-quality t-shirts, masks, onesies, and hoodies for the perfect gift.

Setting up the Project Structure

The purpose of the blog is to render markdown files to good looking blog posts, so let’s create some directories and create our server file:

Now all the files that are going to be our blog posts go into markdown, all template files:

  • index.tmpl.html
  • post.tmpl.html
  • error.tmpl.html

go into our templates directory.

The main.go file is where our server code will live.

List posts and display on Index

Let’s go ahead and list all the markdown files we create in the markdown directory, so an overview of all available posts if you will:

main.go

Let’s go through the file bit by bit:

  1. The r.Delims() function sets the characters we decide are the template tags that we’re going to use in our templates.
  2. The r.GET function defines the route and will respond when / so the root is accessed
  3. We list the files of the directory with ioutil.ReadDir
  4. We loop over the files and put the names into posts with append
  5. We respond with c.HTML, rendering the index template and passing in the posts string array

Next we’ll need an index.tmpl.html file that looks something like this:

Noteworthy about this one is the template loop range that will iterate over the posts. Since it’s a flat array {{ . }} will display the string.

Let’s insert our first post, hello-world.md in our markdown directory. Insert what you like, I have made it:

Compiling Markdown to your Template

Next we want the links to work, so we want to display the individual (compiled) markdown files when somebody tries to access /hello-world.md. For that purpose we’re going to make use of another third party library, blackfriday

Golang Markdown

The Post struct is what we will populate with our Markdown before passing it on to the render function.

It contains a Title and a Content property. The title admittedly is not very useful right now, because it literally is the file name, but we’ll work on that later.

Let’s have a look at how a route could look when serving these MarkDown files to our blog readers:

The important parts of this route function are:

  1. r.GET('/:postName' enables us to use the name of the post inside our route: postName := c.Param('postName')
  2. we’re reading the contents of the markdown file with ioutil.Readfile and convert it to HTML with template.HTML(blackfriday.MarkdownCommon([]byte(mdfile)))
  3. we’re responding with the error template and a 404 error if the file isn’t found
  4. we’re inserting the compiled HTML into the Post struct

Now for the template, we’re going to duplicate the index template and change what’s in the class='container' div:

Which will even make use of our… slightly filenamy title 🙂

Low let’s try to restart our gin server and click on the link on the front page.

You should be seen the content of your MarkDown file in HTML now. This is also the reason why we use the type template.HTML, because we else would see the plain HTML, escaped and literally as the code and not the compiled version that gets interpreted by the browser.

Golang markdown renderer

Adding an 404 Error Page

So far, if we try to access, let’s say: http://localhost:8080/wombat we get a blank page and also our server crashes. That’s because we have not created our error page yet, that we’re using in our blog post display route!

I’ve gone with the following error page template:

Using c.HTML(http.StatusNotFound, 'error.tmpl.html', nil) also sends a 404 status code through HTTP.

Directly below that in our main.go file we’re using return which will cancel the execution of this gin context (request).

Adding Static Assets (Images and Stylesheets)

So far, so good, but what about images and stylesheets?

Luckily somebody wrote static asset serving as a middleware already: gin-contrib/static.

Importing 'github.com/gin-contrib/static' will make it available and if we want to serve files from a directory called assets, we can register the static files like this:

If we want to link images in our post we can now do:

If we want to use a stylesheet in the templates, we can reference them as:

Golang Markdown Renderer

Next Steps and Full Code

Thank you very much for reading! If you want to take your blog adventure further, you could try implementing the following things:

  • Proper post titles
  • Post dates
  • Visitor count statistics

Golang Markdown Generator

Golang markdown to pdf

Here’s the full example code for a very minimal golang blog web app:

Thank you for reading! If you have any comments, additions or questions, please leave them in the form below! You can also tweet them at me

If you want to read more like this, follow me on feedly or other rss readers