mirror of
https://github.com/Alexander-D-Karpov/about.git
synced 2026-03-16 22:06:08 +03:00
178 lines
4.0 KiB
Go
178 lines
4.0 KiB
Go
package assets
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type Bundler struct {
|
|
staticFS embed.FS
|
|
cssBundle []byte
|
|
jsBundle []byte
|
|
cssHash string
|
|
jsHash string
|
|
once sync.Once
|
|
|
|
potatoCSSBundle []byte
|
|
potatoJSBundle []byte
|
|
potatoCSSHash string
|
|
potatoJSHash string
|
|
}
|
|
|
|
func NewBundler(staticFS embed.FS) *Bundler {
|
|
return &Bundler{staticFS: staticFS}
|
|
}
|
|
|
|
func (b *Bundler) Build() {
|
|
b.once.Do(func() {
|
|
b.cssBundle, b.cssHash = b.bundleDir("static/css", ".css", []string{"main.css"}, []string{"potato.css", "admin.css"})
|
|
b.jsBundle, b.jsHash = b.bundleDir("static/js", ".js", []string{"websocket.js", "windowManager.js"}, []string{"potato-windowManager.js", "admin.js"})
|
|
|
|
b.potatoCSSBundle, b.potatoCSSHash = b.bundleDir("static/css", ".css", []string{"potato.css"}, []string{"main.css", "admin.css"})
|
|
b.potatoJSBundle, b.potatoJSHash = b.bundleDir("static/js", ".js", []string{"websocket.js", "potato-windowManager.js"}, []string{"windowManager.js", "admin.js"})
|
|
})
|
|
}
|
|
|
|
func writeHeader(buf bytes.Buffer) bytes.Buffer {
|
|
buf.WriteString("/* Bundled Assets */\n")
|
|
buf.WriteString("/* Bundled by: me! :3 */\n")
|
|
return buf
|
|
}
|
|
|
|
func (b *Bundler) bundleDir(dir, ext string, priorityFirst, exclude []string) ([]byte, string) {
|
|
var buf bytes.Buffer
|
|
buf = writeHeader(buf)
|
|
|
|
files, err := b.listFiles(dir, ext)
|
|
if err != nil {
|
|
return nil, ""
|
|
}
|
|
|
|
excludeMap := make(map[string]bool)
|
|
for _, e := range exclude {
|
|
excludeMap[e] = true
|
|
}
|
|
|
|
priorityMap := make(map[string]int)
|
|
for i, p := range priorityFirst {
|
|
priorityMap[p] = i
|
|
}
|
|
|
|
sort.Slice(files, func(i, j int) bool {
|
|
pi, okI := priorityMap[files[i]]
|
|
pj, okJ := priorityMap[files[j]]
|
|
|
|
if okI && okJ {
|
|
return pi < pj
|
|
}
|
|
if okI {
|
|
return true
|
|
}
|
|
if okJ {
|
|
return false
|
|
}
|
|
|
|
isPluginI := strings.HasPrefix(files[i], "plugin-")
|
|
isPluginJ := strings.HasPrefix(files[j], "plugin-")
|
|
if isPluginI != isPluginJ {
|
|
return !isPluginI
|
|
}
|
|
|
|
return files[i] < files[j]
|
|
})
|
|
|
|
for _, name := range files {
|
|
if excludeMap[name] {
|
|
continue
|
|
}
|
|
|
|
data, err := b.staticFS.ReadFile(filepath.Join(dir, name))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
buf.WriteString(fmt.Sprintf("\n/* === %s === */\n", name))
|
|
buf.Write(data)
|
|
buf.WriteString("\n")
|
|
}
|
|
|
|
hash := fmt.Sprintf("%x", md5.Sum(buf.Bytes()))[:8]
|
|
return buf.Bytes(), hash
|
|
}
|
|
|
|
func (b *Bundler) bundlePotato(dir, ext string, include []string) ([]byte, string) {
|
|
var buf bytes.Buffer
|
|
buf = writeHeader(buf)
|
|
|
|
for _, name := range include {
|
|
data, err := b.staticFS.ReadFile(filepath.Join(dir, name))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
buf.WriteString(fmt.Sprintf("\n/* === %s === */\n", name))
|
|
buf.Write(data)
|
|
buf.WriteString("\n")
|
|
}
|
|
|
|
files, _ := b.listFiles(dir, ext)
|
|
includeMap := make(map[string]bool)
|
|
for _, i := range include {
|
|
includeMap[i] = true
|
|
}
|
|
|
|
for _, name := range files {
|
|
if includeMap[name] {
|
|
continue
|
|
}
|
|
|
|
if strings.Contains(name, "plugin-") && strings.HasPrefix(filepath.Dir(name), "plugins") {
|
|
data, err := b.staticFS.ReadFile(filepath.Join(dir, name))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
buf.WriteString(fmt.Sprintf("\n/* === %s === */\n", name))
|
|
buf.Write(data)
|
|
buf.WriteString("\n")
|
|
}
|
|
}
|
|
|
|
hash := fmt.Sprintf("%x", md5.Sum(buf.Bytes()))[:8]
|
|
return buf.Bytes(), hash
|
|
}
|
|
|
|
func (b *Bundler) listFiles(dir, ext string) ([]string, error) {
|
|
var files []string
|
|
|
|
err := fs.WalkDir(b.staticFS, dir, func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if d.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
if filepath.Ext(path) == ext {
|
|
relPath, _ := filepath.Rel(dir, path)
|
|
files = append(files, relPath)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return files, err
|
|
}
|
|
|
|
func (b *Bundler) CSSBundle() ([]byte, string) { return b.cssBundle, b.cssHash }
|
|
func (b *Bundler) JSBundle() ([]byte, string) { return b.jsBundle, b.jsHash }
|
|
func (b *Bundler) PotatoCSSBundle() ([]byte, string) { return b.potatoCSSBundle, b.potatoCSSHash }
|
|
func (b *Bundler) PotatoJSBundle() ([]byte, string) { return b.potatoJSBundle, b.potatoJSHash }
|