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}