/
generate.go
132 lines (119 loc) · 3.75 KB
/
generate.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
package cmd
import (
"bytes"
"io/ioutil"
"os"
"path"
"strconv"
"text/template"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/yuin/goldmark"
meta "github.com/yuin/goldmark-meta"
"github.com/yuin/goldmark/parser"
)
type generateOptions struct {
context string
output string
}
var generateOpts = &generateOptions{}
var generateCmd = &cobra.Command{
Use: "generate [--context .]",
Short: "Generate the static webiste",
RunE: func(cmd *cobra.Command, args []string) error {
return runGenerate(generateOpts)
},
}
func init() {
generateCmd.PersistentFlags().StringVar(&generateOpts.context, "context", ".", "base path for the proposals repository in your local file system")
generateCmd.PersistentFlags().StringVar(&generateOpts.output, "output", "./site", "where the generate website will be stored")
rootCmd.AddCommand(generateCmd)
}
func runGenerate(opts *generateOptions) error {
proposalsDir := path.Join(opts.context, "proposals")
info, err := os.Stat(proposalsDir)
if os.IsNotExist(err) {
return errors.Wrap(err, "we expect a proposals directory inside the repository.")
}
if info.IsDir() == false {
return errors.New("the expected proposal directory has to be a directory, not a file")
}
files, err := ioutil.ReadDir(proposalsDir)
if err != nil {
return err
}
md := goldmark.New(
goldmark.WithExtensions(
meta.Meta,
),
)
proposalsTable := map[int]struct {
Title string
Status string
Authors string
}{}
for _, f := range files {
readmeFile, err := os.Open(path.Join(proposalsDir, f.Name(), "README.md"))
if err != nil {
return errors.Wrap(err, "error reading the README.md proposal")
}
readme, err := ioutil.ReadAll(readmeFile)
if err != nil {
return errors.Wrap(err, "error reading the README.md proposal")
}
var buf bytes.Buffer
context := parser.NewContext()
if err := md.Convert(readme, &buf, parser.WithContext(context)); err != nil {
panic(err)
}
metaData := meta.Get(context)
id, err := strconv.Atoi(f.Name())
if err != nil {
return err
}
proposalsTable[id] = struct {
Title string
Status string
Authors string
}{
Title: metaData["title"].(string),
Status: metaData["status"].(string),
Authors: metaData["authors"].(string),
}
}
t, err := template.New("site").Parse(t)
err = t.ExecuteTemplate(os.Stdout, "site", proposalsTable)
return nil
}
var t = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0"/>
<title>Tinkerbell's Proposals</title>
<style>
body {margin: 5% auto; background: #f2f2f2; color: #444444; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.8; text-shadow: 0 1px 0 #ffffff; max-width: 73%;}
code {background: white;}
a {border-bottom: 1px solid #444444; color: #444444; text-decoration: none;}
a:hover {border-bottom: 0;}
</style>
</head>
<body>
<div>
<h1>Tinkerbell's Proposals</h1>
</div>
<div>
<p>Tinkerbell uses an open forms of proposals that communities and
contributors can use to discuss evolution of the project. This is a
list of them representing their current state.</p>
</div>
<div>
<ul>
{{ range $key, $value := . }}
<li>[<a href="https://github.com/tinkerbell/proposals/blob/main/proposals/{{ printf "%04d" $key }}/README.md">{{ printf "%04d" $key }}</a>]: {{ $value.Title }} - <b>status:{{ $value.Status }}</b> - authored by: {{ $value.Authors }}</li>
{{ end }}
</ul>
</div>
</body>
</html>
`