forked from pseudomuto/protoc-gen-doc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
renderer.go
150 lines (124 loc) · 3.69 KB
/
renderer.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
145
146
147
148
149
150
package gendoc
import (
"bytes"
"encoding/json"
"errors"
html_template "html/template"
text_template "text/template"
"github.com/Masterminds/sprig"
)
// RenderType is an "enum" for which type of renderer to use.
type RenderType int8
// Available render types.
const (
_ RenderType = iota
RenderTypeDocBook
RenderTypeHTML
RenderTypeJSON
RenderTypeMarkdown
)
// NewRenderType creates a RenderType from the supplied string. If the type is not known, (0, error) is returned. It is
// assumed (by the plugin) that invalid render type simply means that the path to a custom template was supplied.
func NewRenderType(renderType string) (RenderType, error) {
switch renderType {
case "docbook":
return RenderTypeDocBook, nil
case "html":
return RenderTypeHTML, nil
case "json":
return RenderTypeJSON, nil
case "markdown":
return RenderTypeMarkdown, nil
}
return 0, errors.New("Invalid render type")
}
func (rt RenderType) renderer() (Processor, error) {
tmpl, err := rt.template()
if err != nil {
return nil, err
}
switch rt {
case RenderTypeDocBook:
return &textRenderer{string(tmpl)}, nil
case RenderTypeHTML:
return &htmlRenderer{string(tmpl)}, nil
case RenderTypeJSON:
return new(jsonRenderer), nil
case RenderTypeMarkdown:
return &htmlRenderer{string(tmpl)}, nil
}
return nil, errors.New("Unable to create a processor")
}
func (rt RenderType) template() ([]byte, error) {
switch rt {
case RenderTypeDocBook:
return fetchResource("docbook.tmpl")
case RenderTypeHTML:
return fetchResource("html.tmpl")
case RenderTypeJSON:
return nil, nil
case RenderTypeMarkdown:
return fetchResource("markdown.tmpl")
}
return nil, errors.New("Couldn't find template for render type")
}
var funcMap = map[string]interface{}{
"p": PFilter,
"para": ParaFilter,
"nobr": NoBrFilter,
}
// Processor is an interface that is satisfied by all built-in processors (text, html, and json).
type Processor interface {
Apply(template *Template) ([]byte, error)
}
// RenderTemplate renders the template based on the render type. It supports overriding the default input templates by
// supplying a non-empty string as the last parameter.
//
// Example: generating an HTML template (assuming you've got a Template object)
// data, err := RenderTemplate(RenderTypeHTML, &template, "")
//
// Example: generating a custom template (assuming you've got a Template object)
// data, err := RenderTemplate(RenderTypeHTML, &template, "{{range .Files}}{{.Name}}{{end}}")
func RenderTemplate(kind RenderType, template *Template, inputTemplate string) ([]byte, error) {
if inputTemplate != "" {
processor := &textRenderer{inputTemplate}
return processor.Apply(template)
}
processor, err := kind.renderer()
if err != nil {
return nil, err
}
return processor.Apply(template)
}
type textRenderer struct {
inputTemplate string
}
func (mr *textRenderer) Apply(template *Template) ([]byte, error) {
tmpl, err := text_template.New("Text Template").Funcs(funcMap).Funcs(sprig.TxtFuncMap()).Parse(mr.inputTemplate)
if err != nil {
return nil, err
}
var buf bytes.Buffer
if err = tmpl.Execute(&buf, template); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
type htmlRenderer struct {
inputTemplate string
}
func (mr *htmlRenderer) Apply(template *Template) ([]byte, error) {
tmpl, err := html_template.New("Text Template").Funcs(funcMap).Funcs(sprig.HtmlFuncMap()).Parse(mr.inputTemplate)
if err != nil {
return nil, err
}
var buf bytes.Buffer
if err = tmpl.Execute(&buf, template); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
type jsonRenderer struct{}
func (r *jsonRenderer) Apply(template *Template) ([]byte, error) {
return json.MarshalIndent(template, "", " ")
}