From c19dfac86f6b934b0608f8e66e4c0d4c611806e4 Mon Sep 17 00:00:00 2001 From: Jacob McDonnell Date: Wed, 8 Apr 2026 21:06:31 -0400 Subject: refactor: Preprocess Markdown Files Rather than converting markdown files to html on every request, pre convert them during build of the container. --- Dockerfile | 2 ++ MdToHtml | 9 +++++ config.json | 4 +-- main.go | 113 ++++++++++++++++++++++++++---------------------------------- 4 files changed, 61 insertions(+), 67 deletions(-) create mode 100755 MdToHtml diff --git a/Dockerfile b/Dockerfile index 54d44d6..8d285c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,5 +3,7 @@ MAINTAINER Jacob McDonnell EXPOSE 8000 WORKDIR /app COPY . . +RUN apk add pandoc bash +RUN ./MdToHtml RUN go build cmd ["./web"] diff --git a/MdToHtml b/MdToHtml new file mode 100755 index 0000000..39194af --- /dev/null +++ b/MdToHtml @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +for FILE in $(find static -type f -name "*.md"); +do + echo "Processing $FILE..." + pandoc -t html -f markdown "$FILE" > "$(echo "$FILE" | sed 's|\.md$|.html|')" + echo "Done" +done + diff --git a/config.json b/config.json index fe38b72..3400e3a 100644 --- a/config.json +++ b/config.json @@ -11,9 +11,9 @@ "static/logos/favicon16.png", "static/logos/favicon32.png", "static/robots.txt", - "static/home.md" + "static/home.html" ], - "HomeHtml": "static/home.md", + "HomeHtml": "static/home.html", "MainTemplate" : "templates/template.html", "ErrorTemplate" : "templates/error.html" } diff --git a/main.go b/main.go index 6f2ae77..361e3f9 100644 --- a/main.go +++ b/main.go @@ -3,13 +3,10 @@ package main import ( "encoding/json" "fmt" - "github.com/gomarkdown/markdown" - "github.com/gomarkdown/markdown/html" - "github.com/gomarkdown/markdown/parser" "html/template" - "io" "log" "net/http" + "regexp" "os" "slices" ) @@ -24,57 +21,36 @@ type Config struct { var config Config -func GetHome(w http.ResponseWriter, r *http.Request) { - log.Println("Request for:", r.URL.String()) - - if r.URL.String() != "/" { - ErrorPage(w, "Page Not Found.", 404) - return - } - - t := template.Must(template.ParseFiles(config.MainTemplate)) - - html, err := MarkdownToHTML(config.HomeHtml) - if err != nil { - ErrorPage(w, "Internal Server Error", 500) - } else { - t.Execute(w, template.HTML(html)) - } -} - func GetFiles(w http.ResponseWriter, r *http.Request) { log.Println("Request for:", r.URL.String()) url := fmt.Sprintf("static%s", r.URL.String()) - - if slices.Contains(config.Allowed, url) { - http.ServeFile(w, r, url) - } else { - ErrorPage(w, "Page Not Found.", 404) - } -} - -func MarkdownToHTML(path string) (string, error) { - extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock - p := parser.NewWithExtensions(extensions) - - f, err := os.Open(path) + htmlRegex, err := regexp.Compile("^static/.*\\.html$") if err != nil { - return "", err + ErrorPage(w, "Internal Server Error", 500) + return } - defer f.Close() - md, err := io.ReadAll(f) - if err != nil { - return "", err + if url == "static/" { + url = config.HomeHtml } - doc := p.Parse(md) + if slices.Contains(config.Allowed, url) { + if htmlRegex.MatchString(url) { + t := template.Must(template.ParseFiles(config.MainTemplate)) - htmlFlags := html.CommonFlags | html.HrefTargetBlank - opts := html.RendererOptions{Flags: htmlFlags} - renderer := html.NewRenderer(opts) + html, err := os.ReadFile(url) + if err != nil { + ErrorPage(w, "Internal Server Error", 500) + return + } - return string(markdown.Render(doc, renderer)), nil + t.Execute(w, template.HTML(html)) + } else { + http.ServeFile(w, r, url) + } + } else { + ErrorPage(w, "Page Not Found.", 404) + } } func ErrorPage(w http.ResponseWriter, message string, code int) { @@ -93,6 +69,27 @@ func Usage() { fmt.Fprintf(os.Stderr, "%s [--port port]\n", os.Args[0]) } +func ParseConfigFile(path string) error { + configJson, err := os.ReadFile("config.json") + if err != nil { + return err + } + + err = json.Unmarshal(configJson, &config) + return err +} + +func LogConfiguration() { + log.Println("Port:", config.Port) + log.Println("Allowed:") + for i, a := range config.Allowed { + log.Printf("%d: %s\n", i, a) + } + log.Println("HomeHtml:", config.HomeHtml) + log.Println("MainTemplate:", config.MainTemplate) + log.Println("ErrorTemplate:", config.ErrorTemplate) +} + func main() { portFlagSet := false port := ":8000" @@ -113,33 +110,19 @@ func main() { } } - configJson, err := os.ReadFile("config.json") - if err != nil { - panic(err) - } - - err = json.Unmarshal(configJson, &config) + err := ParseConfigFile("config.json") if err != nil { panic(err) } if !portFlagSet { port = ":" + config.Port + } else { + config.Port = port } - fmt.Println(config.Port) - for i, a := range config.Allowed { - fmt.Printf("%d: %s\n", i, a) - } - fmt.Println(config.HomeHtml) - fmt.Println(config.MainTemplate) - fmt.Println(config.ErrorTemplate) - - http.HandleFunc("/robots.txt", GetFiles) - http.HandleFunc("/rss.xml", GetFiles) - http.HandleFunc("/card", GetFiles) - http.HandleFunc("/css/", GetFiles) - http.HandleFunc("/logos/", GetFiles) - http.HandleFunc("/", GetHome) + LogConfiguration() + + http.HandleFunc("/", GetFiles) log.Fatal(http.ListenAndServe(port, nil)) } -- cgit v1.2.3