2020-09-19 10:27:07 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-12-30 11:40:21 +00:00
|
|
|
"bytes"
|
|
|
|
"io"
|
2021-01-10 16:19:08 +00:00
|
|
|
"mime"
|
2020-09-19 10:27:07 +00:00
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
2020-09-19 10:57:14 +00:00
|
|
|
"strings"
|
2021-06-18 12:32:03 +00:00
|
|
|
|
2021-11-15 20:48:16 +00:00
|
|
|
chromahtml "github.com/alecthomas/chroma/formatters/html"
|
2021-06-28 20:17:18 +00:00
|
|
|
"go.goblog.app/app/pkgs/contenttype"
|
2020-09-19 10:27:07 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const assetsFolder = "templates/assets"
|
|
|
|
|
2021-01-10 16:19:08 +00:00
|
|
|
type assetFile struct {
|
|
|
|
contentType string
|
|
|
|
body []byte
|
|
|
|
}
|
2020-09-19 10:27:07 +00:00
|
|
|
|
2022-01-09 20:08:38 +00:00
|
|
|
func (a *goBlog) initTemplateAssets() error {
|
2021-06-06 12:39:42 +00:00
|
|
|
a.assetFileNames = map[string]string{}
|
|
|
|
a.assetFiles = map[string]*assetFile{}
|
2022-01-09 20:08:38 +00:00
|
|
|
if err := filepath.Walk(assetsFolder, func(path string, info os.FileInfo, err error) error {
|
2020-09-19 10:27:07 +00:00
|
|
|
if info.Mode().IsRegular() {
|
2021-12-30 11:40:21 +00:00
|
|
|
// Open file
|
|
|
|
file, err := os.Open(path)
|
2020-09-19 10:27:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-12-30 11:40:21 +00:00
|
|
|
// Compile asset and close file
|
|
|
|
compiled, err := a.compileAsset(path, file)
|
|
|
|
_ = file.Close()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Add to map
|
2020-09-19 10:27:07 +00:00
|
|
|
if compiled != "" {
|
2021-06-06 12:39:42 +00:00
|
|
|
a.assetFileNames[strings.TrimPrefix(path, assetsFolder+"/")] = compiled
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
2022-01-09 20:08:38 +00:00
|
|
|
}); err != nil {
|
2020-09-19 10:27:07 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-11-15 20:48:16 +00:00
|
|
|
// Add syntax highlighting CSS
|
2022-01-09 20:08:38 +00:00
|
|
|
if err := a.initChromaCSS(); err != nil {
|
2021-11-15 20:48:16 +00:00
|
|
|
return err
|
|
|
|
}
|
2020-09-19 10:27:07 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:40:21 +00:00
|
|
|
func (a *goBlog) compileAsset(name string, read io.Reader) (string, error) {
|
2020-09-19 10:27:07 +00:00
|
|
|
ext := path.Ext(name)
|
|
|
|
compiledExt := ext
|
2021-12-30 11:40:21 +00:00
|
|
|
var contentBuffer bytes.Buffer
|
2020-09-19 10:27:07 +00:00
|
|
|
switch ext {
|
|
|
|
case ".js":
|
2021-12-30 11:40:21 +00:00
|
|
|
if err := a.min.Minify(contenttype.JS, &contentBuffer, read); err != nil {
|
2021-02-08 17:51:07 +00:00
|
|
|
return "", err
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
|
|
|
case ".css":
|
2021-12-30 11:40:21 +00:00
|
|
|
if err := a.min.Minify(contenttype.CSS, &contentBuffer, read); err != nil {
|
2021-08-04 13:45:58 +00:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
case ".xml", ".xsl":
|
2021-12-30 11:40:21 +00:00
|
|
|
if err := a.min.Minify(contenttype.XML, &contentBuffer, read); err != nil {
|
2021-02-08 17:51:07 +00:00
|
|
|
return "", err
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
|
|
|
default:
|
2021-12-30 11:40:21 +00:00
|
|
|
if _, err := io.Copy(&contentBuffer, read); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
2021-04-02 08:28:04 +00:00
|
|
|
// Hashes
|
2021-12-30 11:40:21 +00:00
|
|
|
hash, err := getSHA256(bytes.NewReader(contentBuffer.Bytes()))
|
|
|
|
if err != nil {
|
2021-02-08 17:51:07 +00:00
|
|
|
return "", err
|
|
|
|
}
|
2021-04-02 08:28:04 +00:00
|
|
|
// File name
|
2021-12-30 11:40:21 +00:00
|
|
|
compiledFileName := hash + compiledExt
|
2021-04-02 08:28:04 +00:00
|
|
|
// Create struct
|
2021-06-06 12:39:42 +00:00
|
|
|
a.assetFiles[compiledFileName] = &assetFile{
|
2021-01-10 16:19:08 +00:00
|
|
|
contentType: mime.TypeByExtension(compiledExt),
|
2021-12-30 11:40:21 +00:00
|
|
|
body: contentBuffer.Bytes(),
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
2021-02-08 17:51:07 +00:00
|
|
|
return compiledFileName, err
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Function for templates
|
2021-06-06 12:39:42 +00:00
|
|
|
func (a *goBlog) assetFileName(fileName string) string {
|
|
|
|
return "/" + a.assetFileNames[fileName]
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
|
|
|
|
2021-06-06 12:39:42 +00:00
|
|
|
func (a *goBlog) allAssetPaths() []string {
|
2020-09-19 10:27:07 +00:00
|
|
|
var paths []string
|
2021-06-06 12:39:42 +00:00
|
|
|
for _, name := range a.assetFileNames {
|
2020-09-19 10:27:07 +00:00
|
|
|
paths = append(paths, "/"+name)
|
|
|
|
}
|
|
|
|
return paths
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets only called by registered paths
|
2021-06-06 12:39:42 +00:00
|
|
|
func (a *goBlog) serveAsset(w http.ResponseWriter, r *http.Request) {
|
|
|
|
af, ok := a.assetFiles[strings.TrimPrefix(r.URL.Path, "/")]
|
2021-01-10 16:19:08 +00:00
|
|
|
if !ok {
|
2021-06-06 12:39:42 +00:00
|
|
|
a.serve404(w, r)
|
2021-01-10 16:19:08 +00:00
|
|
|
return
|
|
|
|
}
|
2022-02-01 14:58:12 +00:00
|
|
|
w.Header().Set(cacheControl, "public,max-age=31536000,immutable")
|
2021-06-18 12:32:03 +00:00
|
|
|
w.Header().Set(contentType, af.contentType+contenttype.CharsetUtf8Suffix)
|
2021-02-08 17:51:07 +00:00
|
|
|
_, _ = w.Write(af.body)
|
2020-09-19 10:27:07 +00:00
|
|
|
}
|
2021-11-15 20:48:16 +00:00
|
|
|
|
|
|
|
func (a *goBlog) initChromaCSS() error {
|
2021-12-30 11:40:21 +00:00
|
|
|
chromaPath := "css/chroma.css"
|
2021-11-15 20:48:16 +00:00
|
|
|
// Check if file already exists
|
2021-12-30 11:40:21 +00:00
|
|
|
if _, ok := a.assetFiles[chromaPath]; ok {
|
2021-11-15 20:48:16 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// Initialize the style
|
2021-11-16 09:37:30 +00:00
|
|
|
chromaStyleBuilder := chromaGoBlogStyle.Builder()
|
2021-11-15 20:48:16 +00:00
|
|
|
chromaStyle, err := chromaStyleBuilder.Build()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-12-30 11:40:21 +00:00
|
|
|
// Write the CSS to a buffer
|
|
|
|
var cssBuffer bytes.Buffer
|
|
|
|
if err = chromahtml.New(chromahtml.ClassPrefix("c-")).WriteCSS(&cssBuffer, chromaStyle); err != nil {
|
2021-12-07 13:13:09 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-11-15 20:48:16 +00:00
|
|
|
// Compile asset
|
2021-12-30 11:40:21 +00:00
|
|
|
compiled, err := a.compileAsset(chromaPath, &cssBuffer)
|
2021-11-15 20:48:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-12-30 11:40:21 +00:00
|
|
|
// Add to map
|
|
|
|
a.assetFileNames[chromaPath] = compiled
|
2021-11-15 20:48:16 +00:00
|
|
|
return nil
|
|
|
|
}
|