mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
bundle assets
This commit is contained in:
parent
bd43cb60f6
commit
4f6e9e5c7c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
yarr
|
yarr
|
||||||
*.db
|
*.db
|
||||||
|
server/assets_bundle.go
|
||||||
|
81
bundle.go
Normal file
81
bundle.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var code_template = `// autogenerated. do not edit!
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
var assets_bundle = map[string]asset{
|
||||||
|
{{- range .}}
|
||||||
|
"{{.Name}}": {etag: "{{.Etag}}", body: "{{.Body}}"},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
assets = assets_bundle
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type asset struct {
|
||||||
|
Name, Etag, Body string
|
||||||
|
}
|
||||||
|
|
||||||
|
func shasum(b []byte) string {
|
||||||
|
h := sha256.New()
|
||||||
|
h.Write(b)
|
||||||
|
return fmt.Sprintf("%x", h.Sum(nil))[:16]
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(b []byte) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
zw := gzip.NewWriter(&buf)
|
||||||
|
zw.Write(b)
|
||||||
|
zw.Close()
|
||||||
|
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
outfile := "server/assets_bundle.go"
|
||||||
|
assets := make([]asset, 0)
|
||||||
|
filepatterns := []string{
|
||||||
|
"assets/index.html",
|
||||||
|
"assets/graphicarts/*.svg",
|
||||||
|
"assets/graphicarts/*.png",
|
||||||
|
"assets/javascripts/*.js",
|
||||||
|
"assets/stylesheets/*.css",
|
||||||
|
"assets/stylesheets/*.map",
|
||||||
|
}
|
||||||
|
fmt.Printf("%8s %8s %s\n", "original", "encoded", "filename")
|
||||||
|
for _, pattern := range filepatterns {
|
||||||
|
filenames, _ := filepath.Glob(pattern)
|
||||||
|
for _, filename := range filenames {
|
||||||
|
content, _ := ioutil.ReadFile(filename)
|
||||||
|
assets = append(assets, asset{
|
||||||
|
Name: strings.TrimPrefix(filename, "assets/"),
|
||||||
|
Etag: shasum(content),
|
||||||
|
Body: encode(content),
|
||||||
|
})
|
||||||
|
fmt.Printf(
|
||||||
|
"%8d %8d %s\n",
|
||||||
|
len(content),
|
||||||
|
len(assets[len(assets)-1].Body),
|
||||||
|
filename,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
template := template.Must(template.New("code").Parse(code_template))
|
||||||
|
template.Execute(&buf, assets)
|
||||||
|
ioutil.WriteFile(outfile, buf.Bytes(), 0644)
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"encoding/base64"
|
||||||
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/nkanaev/yarr/storage"
|
"github.com/nkanaev/yarr/storage"
|
||||||
"html"
|
"html"
|
||||||
@ -37,6 +40,36 @@ var routes []Route = []Route{
|
|||||||
p("/page", PageCrawlHandler),
|
p("/page", PageCrawlHandler),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type asset struct {
|
||||||
|
etag string
|
||||||
|
body string // base64(gzip(content))
|
||||||
|
gzipped *[]byte
|
||||||
|
decoded *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *asset) gzip() *[]byte {
|
||||||
|
if a.gzipped == nil {
|
||||||
|
gzipped, _ := base64.StdEncoding.DecodeString(a.body)
|
||||||
|
a.gzipped = &gzipped
|
||||||
|
}
|
||||||
|
return a.gzipped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *asset) text() *string {
|
||||||
|
if a.decoded == nil {
|
||||||
|
gzipped, _ := base64.StdEncoding.DecodeString(a.body)
|
||||||
|
reader, _ := gzip.NewReader(bytes.NewBuffer(gzipped))
|
||||||
|
decoded, _ := ioutil.ReadAll(reader)
|
||||||
|
reader.Close()
|
||||||
|
|
||||||
|
decoded_string := string(decoded)
|
||||||
|
a.decoded = &decoded_string
|
||||||
|
}
|
||||||
|
return a.decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
var assets map[string]asset
|
||||||
|
|
||||||
type FolderCreateForm struct {
|
type FolderCreateForm struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
}
|
}
|
||||||
@ -58,6 +91,9 @@ type ItemUpdateForm struct {
|
|||||||
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
t := template.Must(template.New("index.html").Delims("{%", "%}").Funcs(template.FuncMap{
|
t := template.Must(template.New("index.html").Delims("{%", "%}").Funcs(template.FuncMap{
|
||||||
"inline": func(svg string) template.HTML {
|
"inline": func(svg string) template.HTML {
|
||||||
|
if asset, ok := assets["graphicarts/" + svg]; ok {
|
||||||
|
return template.HTML(*asset.text())
|
||||||
|
}
|
||||||
content, _ := ioutil.ReadFile("assets/graphicarts/" + svg)
|
content, _ := ioutil.ReadFile("assets/graphicarts/" + svg)
|
||||||
return template.HTML(content)
|
return template.HTML(content)
|
||||||
},
|
},
|
||||||
@ -67,14 +103,25 @@ func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StaticHandler(rw http.ResponseWriter, req *http.Request) {
|
func StaticHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
path := "assets/" + Vars(req)["path"]
|
path := Vars(req)["path"]
|
||||||
f, err := os.Open(path)
|
ctype := mime.TypeByExtension(filepath.Ext(path))
|
||||||
|
|
||||||
|
if assets != nil {
|
||||||
|
if asset, ok := assets[path]; ok {
|
||||||
|
rw.Header().Set("Content-Type", ctype)
|
||||||
|
rw.Header().Set("Content-Encoding", "gzip")
|
||||||
|
rw.Header().Set("Etag", asset.etag)
|
||||||
|
rw.Write(*asset.gzip())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open("assets/" + path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
rw.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(path)))
|
rw.Header().Set("Content-Type", ctype)
|
||||||
io.Copy(rw, f)
|
io.Copy(rw, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user