@@ -2,10 +2,13 @@ package blocks
2
2
3
3
import (
4
4
"fmt"
5
+ "html/template"
6
+ "io"
5
7
"io/fs"
6
8
"net/http"
7
9
"os"
8
10
"path/filepath"
11
+ "time"
9
12
)
10
13
11
14
func getFS (fsOrDir any ) fs.FS {
@@ -110,3 +113,121 @@ func (f *httpFS) ReadDir(name string) ([]fs.DirEntry, error) {
110
113
111
114
return entries , nil
112
115
}
116
+
117
+ // MemoryFileSystem is a custom file system that holds virtual/memory template files in memory.
118
+ // It completes the fs.FS interface.
119
+ type MemoryFileSystem struct {
120
+ files map [string ]* memoryTemplateFile
121
+ }
122
+
123
+ // NewMemoryFileSystem creates a new VirtualFileSystem instance.
124
+ // It comes with no files, use `ParseTemplate` to add new virtual/memory template files.
125
+ // Usage:
126
+ //
127
+ // vfs := NewVirtualFileSystem()
128
+ // err := vfs.ParseTemplate("example.html", []byte("Hello, World!"), nil)
129
+ // templates := New(vfs)
130
+ // templates.Load()
131
+ func NewMemoryFileSystem () * MemoryFileSystem {
132
+ return & MemoryFileSystem {
133
+ files : make (map [string ]* memoryTemplateFile ),
134
+ }
135
+ }
136
+
137
+ var _ fs.FS = (* MemoryFileSystem )(nil )
138
+
139
+ // ParseTemplate adds a new memory temlate to the file system.
140
+ func (vfs * MemoryFileSystem ) ParseTemplate (name string , contents []byte , funcMap template.FuncMap ) error {
141
+ vfs .files [name ] = & memoryTemplateFile {
142
+ name : name ,
143
+ contents : contents ,
144
+ funcMap : funcMap ,
145
+ }
146
+ return nil
147
+ }
148
+
149
+ // Open implements the fs.FS interface.
150
+ func (vfs * MemoryFileSystem ) Open (name string ) (fs.File , error ) {
151
+ if file , exists := vfs .files [name ]; exists {
152
+ file .reset () // Reset read position
153
+ return file , nil
154
+ }
155
+ return nil , fs .ErrNotExist
156
+ }
157
+
158
+ // memoryTemplateFile represents a memory file.
159
+ type memoryTemplateFile struct {
160
+ name string
161
+ contents []byte
162
+ funcMap template.FuncMap
163
+ offset int64
164
+ }
165
+
166
+ // Ensure memoryTemplateFile implements fs.File interface.
167
+ var _ fs.File = (* memoryTemplateFile )(nil )
168
+
169
+ func (vf * memoryTemplateFile ) reset () {
170
+ vf .offset = 0
171
+ }
172
+
173
+ // Stat implements the fs.File interface, returning file info.
174
+ func (vf * memoryTemplateFile ) Stat () (fs.FileInfo , error ) {
175
+ return & memoryFileInfo {
176
+ name : vf .name ,
177
+ size : int64 (len (vf .contents )),
178
+ }, nil
179
+ }
180
+
181
+ // Read implements the io.Reader interface.
182
+ func (vf * memoryTemplateFile ) Read (p []byte ) (int , error ) {
183
+ if vf .offset >= int64 (len (vf .contents )) {
184
+ return 0 , io .EOF
185
+ }
186
+ n := copy (p , vf .contents [vf .offset :])
187
+ vf .offset += int64 (n )
188
+ return n , nil
189
+ }
190
+
191
+ // Close implements the io.Closer interface.
192
+ func (vf * memoryTemplateFile ) Close () error {
193
+ return nil
194
+ }
195
+
196
+ // memoryFileInfo provides file information for a memory file.
197
+ type memoryFileInfo struct {
198
+ name string
199
+ size int64
200
+ }
201
+
202
+ // Ensure memoryFileInfo implements fs.FileInfo interface.
203
+ var _ fs.FileInfo = (* memoryFileInfo )(nil )
204
+
205
+ // Name returns the base name of the file.
206
+ func (fi * memoryFileInfo ) Name () string {
207
+ return fi .name
208
+ }
209
+
210
+ // Size returns the length in bytes for regular files.
211
+ func (fi * memoryFileInfo ) Size () int64 {
212
+ return fi .size
213
+ }
214
+
215
+ // Mode returns file mode bits.
216
+ func (fi * memoryFileInfo ) Mode () fs.FileMode {
217
+ return 0444 // Read-only
218
+ }
219
+
220
+ // ModTime returns modification time.
221
+ func (fi * memoryFileInfo ) ModTime () time.Time {
222
+ return time .Now ()
223
+ }
224
+
225
+ // IsDir reports if the file is a directory.
226
+ func (fi * memoryFileInfo ) IsDir () bool {
227
+ return false
228
+ }
229
+
230
+ // Sys returns underlying data source (can return nil).
231
+ func (fi * memoryFileInfo ) Sys () interface {} {
232
+ return nil
233
+ }
0 commit comments