krz/skunky-art

Alternative privacy frontend for DeviantArt.

clone: git clone https://gitbay.org/krz/skunky-art.git

v1.3.2: static/templates-noembed.go · raw

  1//go:build !embed
  2// +build !embed
  3
  4package static
  5
  6import (
  7	"bytes"
  8	"io/fs"
  9	"os"
 10	"strings"
 11	"time"
 12)
 13
 14var Templates FS
 15
 16type file struct {
 17	path    string
 18	name    string
 19	content []byte
 20}
 21
 22var templateNames = []string{}
 23var templates = make(map[string][]file)
 24var StaticPath string
 25
 26func CopyTemplatesToMemory() {
 27	baseDir, err := os.ReadDir(StaticPath)
 28	try(err)
 29
 30	for _, c := range baseDir {
 31		if c.IsDir() {
 32			templateNames = append(templateNames, c.Name())
 33
 34			var filePath strings.Builder
 35			filePath.WriteString(StaticPath)
 36			filePath.WriteString("/")
 37			filePath.WriteString(c.Name())
 38
 39			dir, err := os.ReadDir(filePath.String())
 40			try(err)
 41
 42			filePath.WriteString("/")
 43			for _, cd := range dir {
 44				f, err := os.ReadFile(filePath.String() + cd.Name())
 45				try(err)
 46				templates[c.Name()] = append(templates[c.Name()], file{
 47					content: f,
 48					name:    cd.Name(),
 49					path:    c.Name() + "/" + cd.Name(),
 50				})
 51			}
 52		}
 53	}
 54}
 55
 56type FS struct{}
 57
 58func (FS) Open(name string) (fs.File, error) {
 59	for i, l := 0, len(templateNames); i < l; i++ {
 60		for _, x := range templates[templateNames[i]] {
 61			if x.content != nil && name == x.path {
 62				return &File{
 63					name:    x.path,
 64					content: bytes.NewBuffer(x.content),
 65				}, nil
 66			}
 67		}
 68	}
 69	return nil, &fs.PathError{}
 70}
 71
 72func (FS) Glob(pattern string) ([]string, error) {
 73	trimmed := strings.Split(pattern, "/")
 74	var matches = []string{}
 75	for x, s := range templates {
 76		for i, l := 0, len(s); i < l && trimmed[0] == x; i++ {
 77			s := s[i]
 78			matches = append(matches, s.path)
 79		}
 80	}
 81	if len(matches) != 0 {
 82		return matches, nil
 83	}
 84	return nil, &fs.PathError{}
 85}
 86
 87func try(err error) {
 88	if err != nil {
 89		println(err.Error())
 90		os.Exit(1)
 91	}
 92}
 93
 94/* сделано на основе https://github.com/psanford/memfs; требуется для корректной работы templates.ParseFS */
 95type fileInfo struct {
 96	name string
 97}
 98
 99func (fi fileInfo) Name() string {
100	return fi.name
101}
102
103func (fi fileInfo) Size() int64 {
104	return 4096
105}
106
107func (fileInfo) Mode() fs.FileMode {
108	return 0
109}
110
111func (fileInfo) ModTime() time.Time {
112	return time.Time{}
113}
114
115func (fileInfo) IsDir() bool {
116	return false
117}
118
119func (fileInfo) Sys() interface{} {
120	return nil
121}
122
123type File struct {
124	name    string
125	content *bytes.Buffer
126	closed  bool
127}
128
129func (f *File) Stat() (fs.FileInfo, error) {
130	return fileInfo{
131		name: f.name,
132	}, nil
133}
134
135func (f *File) Read(b []byte) (int, error) {
136	if f.closed {
137		return 0, fs.ErrClosed
138	}
139	return f.content.Read(b)
140}
141
142func (f *File) Close() error {
143	if f.closed {
144		return fs.ErrClosed
145	}
146	f.closed = true
147	return nil
148}