view.mdin: /docs/internal/view/md/
Rendering Markdown
Golang has a really good markdown rendering library called
goldmark, and we're going to use it in conjunction
with veun.View
to make our pages.
import (
"bytes"
"context"
"html/template"
"github.com/stanistan/veun"
"github.com/stanistan/veun/el"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
)
Goldmark Configuration
It's actually very very simple to make a trivial wrapper around goldmark.
Similar to veun/template.Template
we want something that takes our
input, and goldmark
uses bytes
, and the configuration
of the library and does what it needs to.
For our use case, we can make a singleton, and if we really want to at some point in the future, make this configurable.
var md = goldmark.New(goldmark.WithExtensions(extension.GFM))
Our HTMLRenderable
This takes a goldmark.Markdown
as an struct parameter, and
defaults to our global md
if it wasn't set.
That's all it takes to make a veun.HTMLRenderable
.
type view struct {
bytes []byte
md goldmark.Markdown
}
func (v view) AsHTML(_ context.Context) (template.HTML, error) {
var r goldmark.Markdown
if v.md != nil {
r = v.md
} else {
r = md
}
var out bytes.Buffer
if err := r.Convert(v.bytes, &out); err != nil {
var empty template.HTML
return empty, err
}
return template.HTML(out.String()), nil
}
Our view
Our view uses just the bytes, and the singleton markdown
.
func (v view) View(_ context.Context) (*veun.View, error) {
return veun.V(v), nil
}
There was another option to have the view
take sources
that can fail, but and produce bytes as output, but this
is fine, and dumb, and simple, and simple is good.
Constructor
This is trivial, and allows us to have more semantic HTML around our generated markdown.
func View(bs []byte) veun.AsView {
return el.Div{
el.Class("md"),
el.Content{view{bytes: bs}},
}
}