in internal/web/render.go [40:151]
func (site *Site) renderHTML(p Page, tmpl string, r *http.Request) ([]byte, error) {
// Clone p, because we are going to set its Content key-value pair.
p2 := make(Page)
for k, v := range p {
p2[k] = v
}
p = p2
url, ok := p["URL"].(string)
if !ok {
// Set URL - caller did not.
p["URL"] = r.URL.Path
}
file, _ := p["File"].(string)
data, _ := p["FileData"].(string)
// Load base template.
base, err := site.readFile(".", tmpl)
if err != nil {
return nil, err
}
dir := strings.Trim(path.Dir(url), "/")
if dir == "" {
dir = "."
}
sd := &siteDir{site, dir}
t := template.New("site.tmpl").Funcs(template.FuncMap{
"add": func(a, b int) int { return a + b },
"sub": func(a, b int) int { return a - b },
"mul": func(a, b int) int { return a * b },
"div": func(a, b int) int { return a / b },
"code": sd.code,
"data": sd.data,
"page": sd.page,
"pages": sd.pages,
"play": sd.play,
"request": func() *http.Request { return r },
"path": func() pkgPath { return pkgPath{} },
"strings": func() pkgStrings { return pkgStrings{} },
"file": sd.file,
"first": first,
"markdown": markdown,
"raw": raw,
"yaml": yamlFn,
"presentStyle": presentStyle,
})
t.Funcs(site.funcs)
if err := tmplfunc.Parse(t, string(base)); err != nil {
return nil, err
}
// Load page-specific layout template.
layout, _ := p["layout"].(string)
if layout == "" {
l, ok := site.findLayout(dir, "default")
if ok {
layout = l
} else {
layout = "none"
}
} else if path.IsAbs(layout) {
layout = strings.TrimLeft(path.Clean(layout+".tmpl"), "/")
} else if strings.Contains(layout, "/") {
layout = path.Join(dir, layout+".tmpl")
} else if layout != "none" {
l, ok := site.findLayout(dir, layout)
if !ok {
return nil, fmt.Errorf("cannot find layout %q", layout)
}
layout = l
}
if layout != "none" {
ldata, err := site.readFile(".", layout)
if err != nil {
return nil, err
}
if err := tmplfunc.Parse(t.New(layout), string(ldata)); err != nil {
return nil, err
}
}
var buf bytes.Buffer
if _, ok := p["Content"]; !ok && data != "" {
// Load actual Markdown content (also a template).
tf := t.New(file)
if err := tmplfunc.Parse(tf, data); err != nil {
return nil, err
}
if err := tf.Execute(&buf, p); err != nil {
return nil, err
}
if strings.HasSuffix(file, ".md") {
html, err := markdownToHTML(buf.String())
if err != nil {
return nil, err
}
p["Content"] = html
} else {
p["Content"] = template.HTML(buf.String())
}
buf.Reset()
}
if err := t.Execute(&buf, p); err != nil {
return nil, err
}
return buf.Bytes(), nil
}