-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.go
144 lines (115 loc) · 3.1 KB
/
render.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package zmdocs
import (
"bytes"
"fmt"
"github.com/sirupsen/logrus"
"github.com/zyra/zmdocs/templates"
"html/template"
"io/ioutil"
"os"
"path/filepath"
)
// Renderer contains all the relevant data to render the docs
type Renderer struct {
MenuItems []*MenuItem
Contexts []*RenderContext
Templates []*Template
}
// Renders all all render contexts and outputs their files
func (r *Renderer) Render() error {
log.WithFields(logrus.Fields{
"menuItems": len(r.MenuItems),
"pages": len(r.Contexts),
"templates": len(r.Templates),
}).Infof("rendering")
var baseTemplateStr string
for _, t := range r.Templates {
if t.Name == "base" {
baseTemplateData, err := ioutil.ReadFile(t.SourceFile)
if err != nil {
return err
}
baseTemplateStr = string(baseTemplateData)
}
}
if baseTemplateStr == "" {
log.Info("no base template was provided, using the default one")
baseTemplateStr = templates.BaseTemplate
}
baseTemplate, err := template.New("").Parse(baseTemplateStr)
if err != nil {
return err
}
log.Debug("starting render process")
for _, ctx := range r.Contexts {
if err := ctx.Render(baseTemplate); err != nil {
return fmt.Errorf("unable to render page: %s", err.Error())
}
}
log.Infof("rendered %d pages", len(r.Contexts))
return nil
}
// A render context contains all required information to render a single page
type RenderContext struct {
Title string
SiteTitle string
Description string
MenuItems []*MenuItem
Content template.HTML
OutDir string
OutFile string
BaseURL string
Link string
l *logrus.Entry
}
// Returns a new render context from the provided file, parser config, and HTML content
func NewRenderContext(f *File, c *ParserConfig, content template.HTML) *RenderContext {
outDir := filepath.Join(c.RootDir, "docs", f.Path)
outFile := filepath.Join(outDir, "index.html")
ctx := RenderContext{
Title: f.Title,
SiteTitle: c.SiteTitle,
Description: c.Description,
MenuItems: c.MenuItems,
Content: content,
OutDir: outDir,
OutFile: outFile,
BaseURL: c.BaseURL,
Link: f.Path,
}
ctx.l = log.WithFields(logrus.Fields{
"title": ctx.Title,
"link": ctx.Link,
})
return &ctx
}
// Renders and outputs the page
func (c *RenderContext) Render(tmpl *template.Template) error {
c.l.Debug("rendering page")
for _, mit := range c.MenuItems {
if mit.Group {
for _, cmit := range mit.Items {
cmit.Active = cmit.Link == c.Link
}
} else if mit.Link == c.Link {
mit.Active = true
} else {
mit.Active = false
}
}
if tmpl != nil {
buff := bytes.NewBuffer(make([]byte, 0))
if err := tmpl.Execute(buff, c); err != nil {
return fmt.Errorf("unable eto execute template: %s", err.Error())
}
c.Content = template.HTML(buff.String())
}
if err := os.MkdirAll(c.OutDir, 0755); err != nil {
return fmt.Errorf("unable to create directory: %s", err.Error())
}
c.l.Debugf("writing file to %s", c.OutFile)
if err := ioutil.WriteFile(c.OutFile, []byte(c.Content), 0644); err != nil {
return fmt.Errorf("unable to write file: %s", err.Error())
}
return nil
}