2021-11-30 15:17:09 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-07-11 04:26:24 +00:00
|
|
|
"bytes"
|
|
|
|
"io"
|
2021-11-30 15:17:09 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2022-07-11 04:26:24 +00:00
|
|
|
"text/template"
|
2021-11-30 15:17:09 +00:00
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
"github.com/tdewolff/minify/v2"
|
|
|
|
minify_css "github.com/tdewolff/minify/v2/css"
|
|
|
|
minify_html "github.com/tdewolff/minify/v2/html"
|
|
|
|
"github.com/yuin/goldmark"
|
|
|
|
gm_extension "github.com/yuin/goldmark/extension"
|
|
|
|
gm_html "github.com/yuin/goldmark/renderer/html"
|
2021-11-30 15:17:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-07-11 04:26:24 +00:00
|
|
|
postFilesPath = "posts"
|
|
|
|
templatePostPath = "templates/post.html"
|
|
|
|
|
|
|
|
templateCSSPath = "templates/styles.css"
|
|
|
|
cssFilename = "styles.css"
|
|
|
|
|
2022-07-10 11:09:42 +00:00
|
|
|
generatedPath = "docs"
|
2022-07-11 04:26:24 +00:00
|
|
|
|
|
|
|
extHTML = ".html"
|
|
|
|
|
|
|
|
mimeTypeHTML = "text/html"
|
|
|
|
mimeTypeCSS = "text/css"
|
2021-11-30 15:17:09 +00:00
|
|
|
)
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
type templatePostData struct {
|
|
|
|
Body string
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:17:09 +00:00
|
|
|
func main() {
|
2022-07-10 11:32:01 +00:00
|
|
|
// Cleanup generated path
|
|
|
|
if err := os.RemoveAll(generatedPath); err != nil {
|
|
|
|
log.Fatalln("Failed to remove all", generatedPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(generatedPath, 0o777); err != nil {
|
|
|
|
log.Fatalln("Failed to mkdir all", generatedPath)
|
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Read post files directory
|
|
|
|
postFiles, err := os.ReadDir(postFilesPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
if err != nil {
|
2022-07-11 04:26:24 +00:00
|
|
|
log.Fatalln("Failed to read dir", postFilesPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Prepare template
|
|
|
|
templatePostBytes, err := os.ReadFile(templatePostPath)
|
2021-11-30 15:17:09 +00:00
|
|
|
if err != nil {
|
2022-07-11 04:26:24 +00:00
|
|
|
log.Fatalln("Failed to read file", templatePostPath, err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
templatePost, err := template.New("post").Parse(string(templatePostBytes))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to parse template", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare parse markdown
|
|
|
|
gm := goldmark.New(
|
|
|
|
goldmark.WithExtensions(
|
|
|
|
gm_extension.GFM,
|
|
|
|
),
|
|
|
|
goldmark.WithRendererOptions(
|
|
|
|
gm_html.WithHardWraps(),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
// Prepare minify
|
|
|
|
m := minify.New()
|
|
|
|
m.AddFunc(mimeTypeHTML, minify_html.Minify)
|
|
|
|
m.AddFunc(mimeTypeCSS, minify_css.Minify)
|
|
|
|
|
|
|
|
// Generate post files
|
|
|
|
for _, postFile := range postFiles {
|
|
|
|
if postFile.IsDir() {
|
2021-11-30 15:17:09 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Prepare post file
|
|
|
|
mdFilename := filepath.Join(postFilesPath, postFile.Name())
|
|
|
|
mdFileBytes, err := os.ReadFile(mdFilename)
|
2021-11-30 15:17:09 +00:00
|
|
|
if err != nil {
|
2022-07-11 04:26:24 +00:00
|
|
|
log.Fatalln("Failed to read file", mdFilename, err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Prepare html file
|
|
|
|
htmlFilename := strings.TrimSuffix(postFile.Name(), filepath.Ext(postFile.Name())) + extHTML
|
|
|
|
htmlFilepath := filepath.Join(generatedPath, htmlFilename)
|
|
|
|
|
|
|
|
htmlFile, err := os.OpenFile(htmlFilepath, os.O_RDWR|os.O_CREATE, 0o600)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to open file", htmlFilepath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse markdown
|
|
|
|
var markdownBuf bytes.Buffer
|
|
|
|
if err := gm.Convert(mdFileBytes, &markdownBuf); err != nil {
|
|
|
|
log.Fatalln("Failed to convert markdown", err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
tmpReader, tmpWriter := io.Pipe()
|
2021-11-30 15:17:09 +00:00
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Template
|
|
|
|
go func() {
|
|
|
|
if err := templatePost.Execute(tmpWriter, templatePostData{
|
|
|
|
Body: markdownBuf.String(),
|
|
|
|
}); err != nil {
|
|
|
|
log.Fatalln("Failed to execute html template", err)
|
|
|
|
}
|
|
|
|
tmpWriter.Close()
|
|
|
|
}()
|
2021-11-30 15:17:09 +00:00
|
|
|
|
2022-07-11 04:26:24 +00:00
|
|
|
// Minify
|
|
|
|
if err := m.Minify(mimeTypeHTML, htmlFile, tmpReader); err != nil {
|
|
|
|
log.Fatalln("Failed to minify html", err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
2022-07-11 04:26:24 +00:00
|
|
|
tmpReader.Close()
|
|
|
|
htmlFile.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy css file
|
|
|
|
templateCSSFile, err := os.OpenFile(templateCSSPath, os.O_RDONLY, 0o600)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to open file", templateCSSPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cssFilename := filepath.Join(generatedPath, cssFilename)
|
|
|
|
cssFile, err := os.OpenFile(cssFilename, os.O_RDWR|os.O_CREATE, 0o600)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Failed to open file", cssFilename, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := m.Minify(mimeTypeCSS, cssFile, templateCSSFile); err != nil {
|
|
|
|
log.Fatalln("Failed to minify css", err)
|
2021-11-30 15:17:09 +00:00
|
|
|
}
|
|
|
|
}
|