Simple Web with Martini + Markdown
I had playing around with go for a while, tho a bit strugling in the beginning due to different language design than those I’ve familiar with, but I love it alot and definitely will use it for some upcoming projects.
it’s taste like shiny sadturday morning at the beach with a cup of coffee and a cigarette
As usual when I learn new programming language, I try to port an exsisting simple code/functionality that I made in other programming language, just to feel how it works and how it differ.
Here I ported small ruby sinatra code, a very simple static website engine using markdown syntax.
CODES
In your working dir at $GOPATH create structures like below:
views
--- master.html
--- homepage.md
main.go
main.go
package main
import (
"fmt"
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/render"
"github.com/russross/blackfriday"
"html/template"
)
func parseMarkdown(args ...interface{}) template.HTML {
s := blackfriday.MarkdownCommon([]byte(fmt.Sprintf("%s", args...)))
return template.HTML(s)
}
func main() {
engine := martini.Classic()
engine.Use(render.Renderer(render.Options{
Directory: "views",
Layout: "master",
Funcs: []template.FuncMap{{"pmd": parseMarkdown}},
Extensions: []string{".md", ".html"},
Charset: "UTF-8",
}))
engine.Get("/", func(r render.Render) {
r.HTML(200, "homepage", map[string]interface{}{"Title": "Golangers"})
})
engine.Run()
}
As you see in the code, we’re importing 3 external packages:
- martini a simple web framework for go which inspired alot from sinatra and express.
- martini-contrib/render a template renderer library for martini, we’ll utilize it to render our layout and page template
- blackfriday a markdown parser library for go
fmt
and html/template
is a built in go library packages for formatting and templating functionality
Instantiate martini
in main()
function we instantiate martini.Classic()
it will give us easy utilization for static file serving, routing etc.
engine := martini.Classic()
Add renderer middleware
then we add rendering middleware to it which will allow us to use dynamic layout and html templating.
engine.Use(render.Renderer(render.Options{
Directory: "views",
Layout: "master",
Funcs: []template.FuncMap{{"pmd": parseMarkdown}},
Extensions: []string{".md", ".html"},
Charset: "UTF-8",
}))
We throw some options into it for customizations
Directory
: where the renderer should lookup the template fileLayout
: the layout name that we will use for our siteExtensions
: the template file extension to lookup for in template directoryFuncs
: slice of template.FuncMap, in this case we add aliaspmd
for our markdown parser functions
func parseMarkdown(args ...interface{}) template.HTML {
s := blackfriday.MarkdownCommon([]byte(fmt.Sprintf("%s", args...)))
return template.HTML(s)
}
the function above is simply parsing arguments passes to it into template.HTML
, where it will be use? we’ll see later down below.
Add routing
Next we add routing to our homepage as follow
engine.Get("/", func(r render.Render) {
r.HTML(200, "homepage", map[string]interface{}{"Title": "Golangers"})
})
Whenever a request to homepage received it will use render
library to parse homepage
template in template directory and give response in HTML format with HTTP 200 OK
code, in addition we feed the renderer with map of key value pairs to be uses in template binding.
views/homepage.md
# Hello Golangers
We're pursuing happy life of being programmers, may golang make it closer.
[@komang](http://twitter.com/komang)
its just a simple markdown template file nothing special
views/master.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ .Title }}</title>
</head>
<body>
{{ yield|pmd }}
</body>
</html>
it’s a dead simple HTML markup with go template binding in it, the {{ .Title }}
will be replaced with Title parameter in map key-val that we passed to renderer in the routing above
then yield is simply stating that the result of template rendering (homepage.md
) will be placed there, then the pipe
and pmd
means that the yielded template will be piped to pmd template function which is refering to our parseMarkdown function.
COMPILE & RUN
Before you could compile the package and run it, you need to resolve all the dependencies
go get .
For easier development we could use Gin a utility to live-reloading our web app
go get github.com/codegangsta/gin
Then compile and run the our web app
$GOPATH/bin/gin main.go
Test the site via browser http://127.0.0.1:3000/
REPOSITORY
I created repository for this simple code at github
Or you could directly get it via go get
go get github.com/chazzuka/go/markdowner
cd $GOPATH/src/github.com/chazzuka/go/markdowner
$GOPATH/bin/gin main.go
Suksma