embed.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package templates
  2. import (
  3. "embed"
  4. "io/fs"
  5. "os"
  6. "path"
  7. "strings"
  8. "github.com/cockroachdb/errors"
  9. "github.com/flamego/template"
  10. "gogs.io/gogs/internal/osutil"
  11. )
  12. //go:embed *.tmpl **/*
  13. var files embed.FS
  14. // templateFile implements the template.File interface.
  15. type templateFile struct {
  16. name string
  17. data []byte
  18. ext string
  19. }
  20. func (tf *templateFile) Name() string {
  21. return tf.name
  22. }
  23. func (tf *templateFile) Data() ([]byte, error) {
  24. return tf.data, nil
  25. }
  26. func (tf *templateFile) Ext() string {
  27. return tf.ext
  28. }
  29. // fileSystem implements the template.FileSystem interface.
  30. type fileSystem struct {
  31. files []template.File
  32. }
  33. func (fs *fileSystem) Files() []template.File {
  34. return fs.files
  35. }
  36. func mustNames(fsys fs.FS) []string {
  37. var names []string
  38. walkDirFunc := func(path string, d fs.DirEntry, err error) error {
  39. if !d.IsDir() {
  40. names = append(names, path)
  41. }
  42. return nil
  43. }
  44. if err := fs.WalkDir(fsys, ".", walkDirFunc); err != nil {
  45. panic("assetNames failure: " + err.Error())
  46. }
  47. return names
  48. }
  49. // NewTemplateFileSystem returns a template.FileSystem instance for embedded assets.
  50. // The argument "dir" can be used to serve subset of embedded assets. Template file
  51. // found under the "customDir" on disk has higher precedence over embedded assets.
  52. func NewTemplateFileSystem(dir, customDir string) template.FileSystem {
  53. if dir != "" && !strings.HasSuffix(dir, "/") {
  54. dir += "/"
  55. }
  56. var err error
  57. var tmplFiles []template.File
  58. names := mustNames(files)
  59. for _, name := range names {
  60. if !strings.HasPrefix(name, dir) {
  61. continue
  62. }
  63. // Check if corresponding custom file exists
  64. var data []byte
  65. fpath := path.Join(customDir, name)
  66. if osutil.IsFile(fpath) {
  67. data, err = os.ReadFile(fpath)
  68. } else {
  69. data, err = files.ReadFile(name)
  70. }
  71. if err != nil {
  72. panic(err)
  73. }
  74. name = strings.TrimPrefix(name, dir)
  75. ext := path.Ext(name)
  76. name = strings.TrimSuffix(name, ext)
  77. tmplFiles = append(tmplFiles, &templateFile{
  78. name: name,
  79. data: data,
  80. ext: ext,
  81. })
  82. }
  83. return &fileSystem{files: tmplFiles}
  84. }