-
Notifications
You must be signed in to change notification settings - Fork 1
/
preview.go
174 lines (154 loc) · 3.51 KB
/
preview.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package cmd
import (
"errors"
"fmt"
"log"
"net/http"
"os"
"path"
"path/filepath"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// port determines the port for the HTTP server to listen for requests on
var port = 1411
var rootDir string
// previewCmd represents the preview command
var previewCmd = &cobra.Command{
Use: "preview [DIR]",
Short: "Preview the Markdown files within directory DIR in a web browser",
Long: `Preview Markdown files located in directory DIR in a web browser.
Launches a server listening on port 1411.
Usage: access file FILE within directory DIR by visiting the following URL:
http://localhost:1411/FILE`,
Run: func(cmd *cobra.Command, args []string) {
var err error
if len(args) != 0 {
err := cmd.Usage()
if err != nil {
panic(err)
}
}
port = viper.GetInt("port")
// Register a handler for the HTTP server
http.HandleFunc("/", handleIt)
address := fmt.Sprintf(":%v", port)
rootDir, err = filepath.Abs(viper.GetString("root"))
if err != nil {
panic(err)
}
if verbose {
fmt.Printf(
"Listening for connections on port " +
color.BlueString(fmt.Sprintf(":%v", viper.GetInt("port"))) +
"\n",
)
fmt.Printf(
"Serving files under root directory: %v\n",
color.YellowString(rootDir),
)
}
// Begin listening for client connections to the HTTP server
log.Fatal(http.ListenAndServe(address, http.HandlerFunc(handleIt)))
},
}
// handleIt handles the current HTTP request
func handleIt(writer http.ResponseWriter, request *http.Request) {
if verbose {
// When we receive a new request, notify the client
fmt.Printf(
"Received request for file %v from host %v",
color.YellowString(request.RequestURI),
color.BlueString(request.RemoteAddr),
)
}
ifile := path.Join(
rootDir,
filepath.Clean(request.URL.Path),
)
// If we cannot find the file they are asking for, notify the client
_, err := os.Stat(ifile)
if errors.Is(err, os.ErrNotExist) {
writer.WriteHeader(404)
message := fmt.Sprintf("<h1>Error 404</h1>\n"+
"<p>File %v not found.</p>",
request.URL.Path,
)
_, err = writer.Write([]byte(message))
if err != nil {
panic(err)
}
return
} else if err != nil {
panic(err)
}
// Read the Markdown contained in the input file
buffer, err := os.ReadFile(ifile)
if err != nil {
writer.WriteHeader(500)
message := fmt.Sprintf("<h1>Error 500</h1>\n"+
"<p>%v</p>",
err.Error(),
)
_, err = writer.Write([]byte(message))
if err != nil {
panic(err)
}
return
}
// Convert the Markdown into HTML
html, err := Convert(buffer)
if err != nil {
writer.WriteHeader(500)
message := fmt.Sprintf("<h1>Error 500</h1>\n"+
"<p>%v</p>",
err.Error(),
)
_, err = writer.Write([]byte(message))
if err != nil {
panic(err)
}
return
}
// Output the resultant HTML
_, err = writer.Write(html)
if err != nil {
writer.WriteHeader(500)
message := fmt.Sprintf("<h1>Error 500</h1>\n"+
"<p>%v</p>",
err.Error(),
)
_, err = writer.Write([]byte(message))
if err != nil {
panic(err)
}
return
}
}
func init() {
rootCmd.AddCommand(previewCmd)
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
previewCmd.Flags().SortFlags = false
previewCmd.Flags().StringVarP(
&rootDir,
"root",
"r",
cwd,
"root directory for the server to server files from\n",
)
previewCmd.Flags().IntVarP(
&port,
"port",
"p",
1411,
"port for the server to listen on\n",
)
err = viper.BindPFlags(previewCmd.Flags())
if err != nil {
panic(err)
}
}