diff --git a/service/fs/spa.go b/service/fs/spa.go deleted file mode 100644 index 3091e6891..000000000 --- a/service/fs/spa.go +++ /dev/null @@ -1,57 +0,0 @@ -package fs - -import ( - "errors" - "io/fs" - "net/http" - "os" - "path" - "path/filepath" - "strings" - - "github.com/yaoapp/gou/application" -) - -// DirSPA is the PWA path -type DirSPA string - -// Open implements FileSystem using os.Open, opening files for reading rooted -// and relative to the directory d. -func (d DirSPA) Open(name string) (http.File, error) { - if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) { - return nil, errors.New("http: invalid character in file path") - } - - dir := string(d) - if dir == "" { - dir = "." - } - - name = filepath.FromSlash(path.Clean("/" + name)) - relName := filepath.Join(dir, name) - - if filepath.Ext(relName) == "" && relName != dir { - relName = filepath.Join(dir, "index.html") - name = filepath.Join(string(os.PathSeparator), "index.html") - } - - // Close dir views Disable directory listing - absName := filepath.Join(application.App.Root(), relName) - stat, err := os.Stat(absName) - if err != nil { - return nil, mapOpenError(err, relName, filepath.Separator, os.Stat) - } - - if stat.IsDir() { - if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) { - return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat) - } - } - - f, err := application.App.FS(string(d)).Open(name) - if err != nil { - return nil, mapOpenError(err, relName, filepath.Separator, os.Stat) - } - - return f, nil -} diff --git a/service/fs/sui.go b/service/fs/sui.go deleted file mode 100644 index 67ea94648..000000000 --- a/service/fs/sui.go +++ /dev/null @@ -1,57 +0,0 @@ -package fs - -import ( - "errors" - "io/fs" - "net/http" - "os" - "path" - "path/filepath" - "strings" - - "github.com/yaoapp/gou/application" -) - -// DirSUI is the PWA path -type DirSUI string - -// Open implements FileSystem using os.Open, opening files for reading rooted -// and relative to the directory d. -func (d DirSUI) Open(name string) (http.File, error) { - if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) { - return nil, errors.New("http: invalid character in file path") - } - - dir := string(d) - if dir == "" { - dir = "." - } - - name = filepath.FromSlash(path.Clean("/" + name)) - relName := filepath.Join(dir, name) - - if filepath.Ext(relName) == "" && relName != dir { - relName = filepath.Join(dir, "index.html") - name = filepath.Join(string(os.PathSeparator), "index.html") - } - - // Close dir views Disable directory listing - absName := filepath.Join(application.App.Root(), relName) - stat, err := os.Stat(absName) - if err != nil { - return nil, mapOpenError(err, relName, filepath.Separator, os.Stat) - } - - if stat.IsDir() { - if _, err := os.Stat(filepath.Join(absName, "index.html")); os.IsNotExist(err) { - return nil, mapOpenError(fs.ErrNotExist, relName, filepath.Separator, os.Stat) - } - } - - f, err := application.App.FS(string(d)).Open(name) - if err != nil { - return nil, mapOpenError(err, relName, filepath.Separator, os.Stat) - } - - return f, nil -} diff --git a/service/middleware.go b/service/middleware.go index 9b0786e90..ca9661930 100644 --- a/service/middleware.go +++ b/service/middleware.go @@ -47,6 +47,14 @@ func withStaticFileServer(c *gin.Context) { } } + // Sui file server + if strings.HasSuffix(c.Request.URL.Path, ".sui") { + data := []byte(`SUI Server: ` + c.Request.URL.Path) + c.Data(200, "text/html; charset=utf-8", data) + c.Done() + return + } + // static file server AppFileServer.ServeHTTP(c.Writer, c.Request) c.Abort() diff --git a/sui/core/compile.go b/sui/core/compile.go index a6e9a9499..6ac2e74f6 100644 --- a/sui/core/compile.go +++ b/sui/core/compile.go @@ -24,12 +24,20 @@ func (page *Page) Compile(option *BuildOption) (string, error) { } if page.Codes.DATA.Code != "" { - doc.Find("body").AppendHtml(`\n", + doc.Find("body").AppendHtml("\n\n" + `\n\n", ) } + // add the route data + doc.Find("body").AppendHtml(`\n") + html, err := doc.Html() if err != nil { return "", err diff --git a/sui/core/fs.go b/sui/core/fs.go new file mode 100644 index 000000000..3279f6aa5 --- /dev/null +++ b/sui/core/fs.go @@ -0,0 +1,98 @@ +package core + +import ( + "bytes" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gin-gonic/gin" + "github.com/yaoapp/gou/application" +) + +// SuiFile is a custom implementation of http.File +type SuiFile struct { + reader io.Reader + size int64 + name string +} + +// SuiFileInfo is a custom implementation of os.FileInfo +type SuiFileInfo struct { + size int64 + name string +} + +// Open is a custom implementation of http.FileSystem +func Open(c *gin.Context, path string, name string) (http.File, error) { + root := application.App.Root() + pathName := filepath.Join(root, path, name) + data := []byte(fmt.Sprintf(`SUI Server: %s`, pathName)) + return &SuiFile{ + reader: bytes.NewReader(data), + size: int64(len(data)), + name: filepath.Base(name) + ".html", + }, nil +} + +// Close is a custom implementation of the Close method for SuiFile +func (file *SuiFile) Close() error { + file.reader = nil + return nil +} + +// Read is a custom implementation of the Read method for SuiFile +func (file *SuiFile) Read(b []byte) (n int, err error) { + // Use the custom SuiFile reader + return file.reader.Read(b) +} + +// Seek is a custom implementation of the Seek method for SuiFile +func (file *SuiFile) Seek(offset int64, whence int) (int64, error) { + // Use the Seek method of the underlying os.File + return 0, nil +} + +// Readdir is a custom implementation of the Readdir method for SuiFile +func (file *SuiFile) Readdir(n int) ([]os.FileInfo, error) { + // Use the Readdir method of the underlying os.File + return nil, nil +} + +// Stat is a custom implementation of the Stat method for SuiFile +func (file *SuiFile) Stat() (os.FileInfo, error) { + return &SuiFileInfo{size: file.size, name: file.name}, nil +} + +// Size is a custom implementation of os.FileInfo +func (info *SuiFileInfo) Size() int64 { + return info.size +} + +// Name is a custom implementation of os.FileInfo +func (info *SuiFileInfo) Name() string { + return info.name +} + +// Mode is a custom implementation of os.FileInfo +func (info *SuiFileInfo) Mode() os.FileMode { + return 0 +} + +// ModTime is a custom implementation of os.FileInfo +func (info *SuiFileInfo) ModTime() time.Time { + return time.Now() +} + +// IsDir is a custom implementation of os.FileInfo +func (info *SuiFileInfo) IsDir() bool { + return false +} + +// Sys is a custom implementation of os.FileInfo +func (info *SuiFileInfo) Sys() interface{} { + return nil +} diff --git a/sui/core/fs_test.go b/sui/core/fs_test.go new file mode 100644 index 000000000..9a8bc9592 --- /dev/null +++ b/sui/core/fs_test.go @@ -0,0 +1 @@ +package core