simple markdown builder in golang
Tags: go, showdev, builder, markdown
Published: 2023-10-22 14:36:31

## Do you like text/template?
When you need to dynamically generate Markdown, which method do you prefer? Do you use data-driven templates like [text/template](https://pkg.go.dev/text/template) or [html/template](https://pkg.go.dev/html/template)?

I'm not particularly fond of templates. They tend to bigger over time, starting small and growing unwieldy. So, taking inspiration from the GoF Design Pattern Builder, I created a simple Markdown Builder library.

## [go-spectest/markdown](https://github.com/go-spectest/markdown)
The markdown package are cross-platform compatible. It works Linux, macOS, Windows:) It has a simple design and a test coverage exceeding 90%. The markdown package will make Markdown generation easy.

However, unlike templates, they do not support conditional branching. Therefore, they can only generate **very basic markdown**. However, I believe some people (including myself) find this level of functionality to be sufficient.

## Sample code
```go
package main

import (
	"os"

	md "github.com/go-spectest/markdown"
)

func main() {
	md.NewMarkdown(os.Stdout).
		H1("This is H1").
		PlainText("This is plain text").
		H2f("This is %s with text format", "H2").
		PlainTextf("Text formatting, such as %s and %s, %s styles.",
			md.Bold("bold"), md.Italic("italic"), md.Code("code")).
		H2("Code Block").
		CodeBlocks(md.SyntaxHighlightGo,
			`package main
import "fmt"

func main() {
	fmt.Println("Hello, World!")
}`).
		H2("List").
		BulletList("Bullet Item 1", "Bullet Item 2", "Bullet Item 3").
		OrderedList("Ordered Item 1", "Ordered Item 2", "Ordered Item 3").
		H2("CheckBox").
		CheckBox([]md.CheckBoxSet{
			{Checked: false, Text: md.Code("sample code")},
			{Checked: true, Text: md.Link("Go", "https://golang.org")},
			{Checked: false, Text: md.Strikethrough("strikethrough")},
		}).
		H2("Blockquote").
		Blockquote("If you can dream it, you can do it.").
		H3("Horizontal Rule").
		HorizontalRule().
		H2("Table").
		Table(md.TableSet{
			Header: []string{"Name", "Age", "Country"},
			Rows: [][]string{
				{"David", "23", "USA"},
				{"John", "30", "UK"},
				{"Bob", "25", "Canada"},
			},
		}).
		H2("Image").
		PlainTextf(md.Image("sample_image", "./sample.png")).
		Build()
}
```

Output:

<pre>
# This is H1
This is plain text
  
## This is H2 with text format
Text formatting, such as **bold** and *italic*, `code` styles.
  
## Code Block
```go
package main
import "fmt"

func main() {
        fmt.Println("Hello, World!")
}
```
  
## List
- Bullet Item 1
- Bullet Item 2
- Bullet Item 3
1. Ordered Item 1
2. Ordered Item 2
3. Ordered Item 3
  
## CheckBox
- [ ] `sample code`
- [x] [Go](https://golang.org)
- [ ] ~~strikethrough~~
  
## Blockquote
> If you can dream it, you can do it.
  
### Horizontal Rule
---
  
## Table
| NAME  | AGE | COUNTRY |
|-------|-----|---------|
| David |  23 | USA     |
| John  |  30 | UK      |
| Bob   |  25 | Canada  |

## Image
![sample_image](./sample.png)
</pre>

## Supported Markdown features
- Heading; H1, H2, H3, H4, H5, H6
- Blockquote
- Bullet list
- Ordered list
- Checkbox list
- Code blocks
- Horizontal rule
- Table
- Text formatting; bold, italic, code, strikethrough, bold italic
- Text with link
- Text with image
- Plain text
- Details

## Related projects
[go-spectest/markdown](https://github.com/go-spectest/markdown) is a side project of [go-spectest/spectest](https://github.com/go-spectest/spectest). spectest is a project forked from [steinfletcher/apitest](https://github.com/steinfletcher/apitest), a library that assists in API end-to-end testing.

The spectest was forked to enhance the documentation generation functionality of apitest. It currently adds the capability to reflect images in the documentation if the response body is an image during document generation.

![sample document](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rekgxhtbrqo2rxl990vj.png)


To generate documentation more flexibly, I considered changing the document file format from HTML to Markdown. In the process, [go-spectest/markdown](https://github.com/go-spectest/markdown) was implemented.

## Next work
GitHub's Markdown supports mermaid (diagramming and charting tool), which is very powerful for expressing specifications.

Therefore, I am thinking of creating a Mermaid Builder :) If anyone knows of a Mermaid Builder written in Golang, please let me know. I might not have to implement it myself.

Thank you for reading.