-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmd.go
130 lines (105 loc) · 3.02 KB
/
md.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
package main
import (
"bytes"
"errors"
"fmt"
"os"
"path"
"path/filepath"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark-highlighting/v2"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
)
type MDConverter struct {
inputPath string
outputPath string
templatePath string
}
// Takes an absolute .md path and attempts to output rendered html to the [MDConverter].outputPath.
// Returns the m.outputPath if successful.
func (m *MDConverter) Convert() (string, error) {
md := goldmark.New(
goldmark.WithExtensions(
extension.GFM,
highlighting.NewHighlighting(
highlighting.WithStyle("vs"),
),
),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
)
source, err := m.getSource()
if err != nil {
return "", fmt.Errorf("get source from m.inputpath, %v: %v", source, err)
}
var convertBuffer bytes.Buffer
err = md.Convert(source, &convertBuffer)
if err != nil {
return "", fmt.Errorf("convert md %v: %v", source, md)
}
htmlOutput := make([]byte, convertBuffer.Len())
br, err := convertBuffer.Read(htmlOutput)
if err != nil {
return "", fmt.Errorf("read converted htmlOutput to buf %v: %v, bytes read: %v", htmlOutput, err, br)
}
out, err := m.makeOutput(htmlOutput)
if err != nil {
return "", fmt.Errorf("failed make output %v: %v", out, err)
}
return m.outputPath, nil
}
func (m *MDConverter) getSource() ([]byte, error) {
if !path.IsAbs(m.inputPath) {
return make([]byte, 0), errors.New("Invalid inputPath, please provide absolute path to .md file.")
}
inputFile, err := os.OpenFile(m.inputPath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return make([]byte, 0), fmt.Errorf("open file %v: %v", inputFile, err)
}
defer inputFile.Close()
fileInfo, err := inputFile.Stat()
if err != nil {
return make([]byte, 0), fmt.Errorf("file info %v: %v", fileInfo, err)
}
source := make([]byte, fileInfo.Size())
br, err := inputFile.Read(source)
if err != nil {
return make([]byte, 0), fmt.Errorf("read %v to source buffer: %v, bytes read: %d", source, err, br)
}
return source, nil
}
func (m *MDConverter) makeOutput(convertedHtml []byte) ([]byte, error) {
output, err := m.makeOutputDir()
if err != nil {
return make([]byte, 0), fmt.Errorf("create file %v: %v, %v", m.outputPath, err, output)
}
defer output.Close()
tmpl := TemplateMaker{
inputPath: m.templatePath,
}
type PageData struct {
PageTitle string
ConvertedHtml string
}
pageData := PageData{
PageTitle: "Testing template from md",
ConvertedHtml: string(convertedHtml),
}
out, err := tmpl.Execute(pageData)
if err != nil {
return make([]byte, 0), fmt.Errorf("fail tmpl execute %v, %v: %v", pageData, out, err)
}
bw, err := output.Write(out)
if err != nil {
return make([]byte, 0), fmt.Errorf("write out to file %v, %v: %v, bw: %v", out, m.outputPath, err, bw)
}
return out, nil
}
func (m *MDConverter) makeOutputDir() (*os.File, error) {
if err := os.MkdirAll(filepath.Dir(m.outputPath), 0770); err != nil {
return nil, err
}
return os.Create(m.outputPath)
}