render.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package routes
  2. import (
  3. "io"
  4. "log"
  5. "reflect"
  6. "strings"
  7. "codeberg.org/vnpower/pixivfe/v2/session"
  8. "codeberg.org/vnpower/pixivfe/v2/utils"
  9. "github.com/CloudyKit/jet/v6"
  10. "github.com/gofiber/fiber/v2"
  11. )
  12. // global variable, yes.
  13. var views *jet.Set
  14. func InitTemplatingEngine(InDevelopment bool) {
  15. if InDevelopment {
  16. views = jet.NewSet(
  17. jet.NewOSFileSystemLoader("assets/views"),
  18. jet.InDevelopmentMode(), // disable cache
  19. )
  20. } else {
  21. views = jet.NewSet(
  22. jet.NewOSFileSystemLoader("assets/views"),
  23. )
  24. }
  25. for fn_name, fn := range utils.GetTemplateFunctions() {
  26. views.AddGlobal(fn_name, fn)
  27. }
  28. }
  29. func Render[T any](c *fiber.Ctx, data T) error {
  30. // Pass in values that we want to be available to all pages here
  31. token := session.GetPixivToken(c)
  32. pageURL := c.BaseURL() + c.OriginalURL()
  33. cookies := map[string]string{}
  34. for _, name := range session.AllCookieNames {
  35. value := session.GetCookie(c, name)
  36. cookies[string(name)] = value
  37. }
  38. variables := jet.VarMap{}
  39. // The middleware at line 99 in `main.go` cannot bind these values below if we use this function.
  40. variables.Set("BaseURL", c.BaseURL())
  41. variables.Set("OriginalURL", c.OriginalURL())
  42. variables.Set("PageURL", pageURL)
  43. variables.Set("LoggedIn", token != "")
  44. variables.Set("Queries", c.Queries())
  45. variables.Set("CookieList", cookies)
  46. c.Context().SetContentType("text/html; charset=utf-8")
  47. return RenderInner(c.Response().BodyWriter(), variables, data)
  48. }
  49. func RenderInner[T any](w io.Writer, variables jet.VarMap, data T) error {
  50. template_name, found := strings.CutPrefix(reflect.TypeFor[T]().Name(), "Data_")
  51. if !found {
  52. log.Panicf("struct name does not start with 'Data_': %s", template_name)
  53. }
  54. template, err := views.GetTemplate(template_name + ".jet.html")
  55. if err != nil {
  56. return err
  57. }
  58. views.Parse(template_name+".jet.html", template.String())
  59. return template.Execute(w, variables, data)
  60. }
  61. // func structToMap[T any](data T) map[string]any {
  62. // result := map[string]any{}
  63. // Type := reflect.TypeFor[T]()
  64. // for i := 0; i < Type.NumField(); i += 1 {
  65. // field := Type.Field(i)
  66. // result[field.Name] = fieldName(data, field.Name)
  67. // }
  68. // return result
  69. // }
  70. // // assumes that the field `field_name` exists, panics otherwise
  71. // func fieldName[T any](data T, field_name string) any {
  72. // return reflect.ValueOf(data).FieldByName(field_name).Interface()
  73. // }