diff --git a/assets/views/following.jet.html b/assets/views/following.jet.html
index c740146..2a87651 100644
--- a/assets/views/following.jet.html
+++ b/assets/views/following.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Newest works from people you follow
diff --git a/assets/views/index.jet.html b/assets/views/index.jet.html
index d7592d8..8c6ccd8 100644
--- a/assets/views/index.jet.html
+++ b/assets/views/index.jet.html
@@ -1,15 +1,15 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
-{{ if isset(NoTokenData) }}
+{{ if !.LoggedIn }}
Not logged in. You can login here.
- {{ include "components/ranking-tn" NoTokenData.Contents }}
+ {{ include "components/ranking-tn" .NoTokenData.Contents }}
{{ else }}
@@ -23,15 +23,15 @@
See more
- {{ include "components/small-tn" Data.Following }}
+ {{ include "components/small-tn" .Data.Following }}
Recommended works
- {{ include "components/small-tn" Data.Recommended }}
+ {{ include "components/small-tn" .Data.Recommended }}
- {{ range Data.RecommendByTags }}
+ {{ range .Data.RecommendByTags }}
Recommended illustrations tagged #{{.Name}}
{{ include "components/small-tn" .Artworks }}
diff --git a/assets/views/newest.jet.html b/assets/views/newest.jet.html
index 8d9ae45..67414b9 100644
--- a/assets/views/newest.jet.html
+++ b/assets/views/newest.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Newest works from all users
diff --git a/assets/views/novel.jet.html b/assets/views/novel.jet.html
index 2aa6ad9..e50fc6a 100644
--- a/assets/views/novel.jet.html
+++ b/assets/views/novel.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
diff --git a/assets/views/novelDiscovery.jet.html b/assets/views/novelDiscovery.jet.html
index 5f438f5..d2a233b 100644
--- a/assets/views/novelDiscovery.jet.html
+++ b/assets/views/novelDiscovery.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Discover novels
diff --git a/assets/views/pixivision.jet.html b/assets/views/pixivision.jet.html
index d9d21d9..dc23456 100644
--- a/assets/views/pixivision.jet.html
+++ b/assets/views/pixivision.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
diff --git a/assets/views/pixivision_article.jet.html b/assets/views/pixivision_article.jet.html
index 3fbb418..f7f1b1b 100644
--- a/assets/views/pixivision_article.jet.html
+++ b/assets/views/pixivision_article.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{{Article.Title}}
diff --git a/assets/views/rank.jet.html b/assets/views/rank.jet.html
index 93dcd57..2deeb1d 100644
--- a/assets/views/rank.jet.html
+++ b/assets/views/rank.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{{ import "components/switcher" }}
diff --git a/assets/views/rankingCalendar.jet.html b/assets/views/rankingCalendar.jet.html
index bc5770d..df87281 100644
--- a/assets/views/rankingCalendar.jet.html
+++ b/assets/views/rankingCalendar.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Ranking calendar ({{ ThisMonth.MonthLiteral }} {{ Year }})
diff --git a/assets/views/settings.jet.html b/assets/views/settings.jet.html
index 73f5a43..a9bdf92 100644
--- a/assets/views/settings.jet.html
+++ b/assets/views/settings.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Settings
diff --git a/assets/views/tag.jet.html b/assets/views/tag.jet.html
index bb01fcc..baa077f 100644
--- a/assets/views/tag.jet.html
+++ b/assets/views/tag.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{{ import "components/switcher" }}
diff --git a/assets/views/temp.jet.html b/assets/views/temp.jet.html
index a64899d..031030a 100644
--- a/assets/views/temp.jet.html
+++ b/assets/views/temp.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{{ if Token }}
diff --git a/assets/views/unauthorized.jet.html b/assets/views/unauthorized.jet.html
index 8c539cd..041dd15 100644
--- a/assets/views/unauthorized.jet.html
+++ b/assets/views/unauthorized.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
Unauthorized
diff --git a/assets/views/user.jet.html b/assets/views/user.jet.html
index 4aeb98c..6246139 100644
--- a/assets/views/user.jet.html
+++ b/assets/views/user.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{{ if ! User.BackgroundImage }}
diff --git a/assets/views/userAtom.jet.html b/assets/views/userAtom.jet.html
index 6061299..041e030 100644
--- a/assets/views/userAtom.jet.html
+++ b/assets/views/userAtom.jet.html
@@ -1,4 +1,4 @@
-{{extends "layout/default.jet"}}
+{{extends "layout/default.jet.html"}}
{{block body()}}
{* *}
diff --git a/doc/dev/framework-migration.md b/doc/dev/framework-migration.md
index b87a8cf..2848741 100644
--- a/doc/dev/framework-migration.md
+++ b/doc/dev/framework-migration.md
@@ -7,8 +7,9 @@ Then, the templating engine is decoupled from gofiber.
### Fixing current templates
-gofiber doesn't mention this crucial distinction of Jet: the difference between variables (e.g. PageURL) and data (the data parameter to `Render(...)`).
+If you see error like ` not found in map[...]` when visiting a page, you need to add a dot before all data member access. e.g. from `Illust` to `.Illust`.
-Data access must be prefixed with a dot. `.Illust` is valid. `Illust` is a variable but not data.
+gofiber doesn't mention this.
+In Jet, variables are accessed without a dot (`PageURL`), while data members (the `data` parameter to `Render(...)`). are accessed with a dot in front.
Current templates use the variable style (`Illust`), but that is wrong.
diff --git a/routes/index.go b/routes/index.go
index 07dd9bd..acf28ab 100644
--- a/routes/index.go
+++ b/routes/index.go
@@ -18,8 +18,10 @@ func IndexPage(c *fiber.Ctx) error {
return err
}
- return c.Render("index", fiber.Map{
- "Title": "Landing", "Data": works,
+ return Render(c, Data_index{
+ Title: "Landing",
+ Data: *works,
+ IsLoggedIn: true,
})
}
@@ -28,8 +30,10 @@ func IndexPage(c *fiber.Ctx) error {
if err != nil {
return err
}
- return c.Render("index", fiber.Map{
- "Title": "Landing", "NoTokenData": works,
+ return Render(c, Data_index{
+ Title: "Landing",
+ NoTokenData: works,
+ IsLoggedIn: false,
})
}
diff --git a/routes/render.go b/routes/render.go
new file mode 100644
index 0000000..26aa6c7
--- /dev/null
+++ b/routes/render.go
@@ -0,0 +1,84 @@
+package routes
+
+import (
+ "log"
+ "reflect"
+ "strings"
+
+ "codeberg.org/vnpower/pixivfe/v2/session"
+ "codeberg.org/vnpower/pixivfe/v2/utils"
+
+ "github.com/CloudyKit/jet/v6"
+ "github.com/gofiber/fiber/v2"
+)
+
+// global variable, yes.
+var views *jet.Set
+
+func InitTemplatingEngine(InDevelopment bool) {
+ if InDevelopment {
+ views = jet.NewSet(
+ jet.NewOSFileSystemLoader("assets/views"),
+ jet.InDevelopmentMode(), // disable cache
+ )
+ } else {
+ views = jet.NewSet(
+ jet.NewOSFileSystemLoader("assets/views"),
+ )
+ }
+ for fn_name, fn := range utils.GetTemplateFunctions() {
+ views.AddGlobal(fn_name, fn)
+ }
+}
+
+func Render[T any](c *fiber.Ctx, data T) error {
+ template_name, found := strings.CutPrefix(reflect.TypeFor[T]().Name(), "Data_")
+ if !found {
+ log.Panicf("struct name does not start with 'Data_': %s", template_name)
+ }
+
+ // Pass in values that we want to be available to all pages here
+ token := session.GetPixivToken(c)
+ pageURL := c.BaseURL() + c.OriginalURL()
+
+ cookies := map[string]string{}
+ for _, name := range session.AllCookieNames {
+ value := session.GetCookie(c, name)
+ cookies[string(name)] = value
+ }
+
+ template, err := views.GetTemplate(template_name + ".jet.html")
+ if err != nil {
+ return err
+ }
+
+ views.Parse(template_name + ".jet.html", template.String())
+
+ variables := jet.VarMap{}
+
+ // The middleware at line 99 in `main.go` cannot bind these values below if we use this function.
+ variables.Set("BaseURL", c.BaseURL())
+ variables.Set("OriginalURL", c.OriginalURL())
+ variables.Set("PageURL", pageURL)
+ variables.Set("LoggedIn", token != "")
+ variables.Set("Queries", c.Queries())
+ variables.Set("CookieList", cookies)
+
+ c.Context().SetContentType("text/html; charset=utf-8")
+ return template.Execute(c.Response().BodyWriter(), variables, data)
+}
+
+// func structToMap[T any](data T) map[string]any {
+// result := map[string]any{}
+// Type := reflect.TypeFor[T]()
+// for i := 0; i < Type.NumField(); i += 1 {
+// field := Type.Field(i)
+// result[field.Name] = fieldName(data, field.Name)
+// }
+// return result
+// }
+
+// // assumes that the field `field_name` exists, panics otherwise
+// func fieldName[T any](data T, field_name string) any {
+// return reflect.ValueOf(data).FieldByName(field_name).Interface()
+// }
diff --git a/routes/render_.go b/routes/render_.go
deleted file mode 100644
index 3fa4a95..0000000
--- a/routes/render_.go
+++ /dev/null
@@ -1,207 +0,0 @@
-package routes
-
-import (
- "log"
- "reflect"
- "strings"
-
- "codeberg.org/vnpower/pixivfe/v2/core"
- "codeberg.org/vnpower/pixivfe/v2/session"
- "codeberg.org/vnpower/pixivfe/v2/utils"
-
- "github.com/CloudyKit/jet/v6"
- "github.com/gofiber/fiber/v2"
-)
-
-type Data_error struct {
- Title string
- Error error
-}
-type Data_about struct {
- Time string
- Version string
- ImageProxy string
- AcceptLanguage string
-}
-type Data_artwork struct {
- Illust core.Illust // faker can't fill this
- Title string
- MetaDescription string
- MetaImage string
- MetaAuthor string
- MetaAuthorID string
-}
-type Data_artworkMulti struct {
- Artworks []core.Illust
- Title string
-}
-type Data_userAtom struct {
- URL string
- Title string
- User core.User
- Category core.UserArtCategory
- Updated string
- PageLimit int
- Page int
- // MetaImage string
-}
-
-// below are unconverted. types may be wrong.
-type Data_discovery struct {
- Artworks string
- Title string
- Queries string
-}
-type Data_novelDiscovery struct {
- Novels string
- Title string
-}
-type Data_index struct {
- Title string
- Data string
-}
-type Data_newest struct {
- Items string
- Title string
-}
-type Data_novel struct {
- Novel string
- NovelRelated string
- User string
- Title string
- FontType string
- ViewMode string
- Language string
-}
-type Data_unauthorized struct{}
-type Data_following struct {
- Title string
- Mode string
- Artworks string
- CurPage string
- Page string
-}
-
-// type Data_pixivisionindex struct {
-// Data string
-// }
-//
-// type Data_pixivisionarticle struct {
-// Article string
-// }
-type Data_rank struct {
- Title string
- Page string
- PageLimit int
- Date string
- Data string
-}
-type Data_rankingCalendar struct {
- Title string
- Render string
- Mode string
- Year string
- MonthBefore string
- MonthAfter string
- ThisMonth string
-}
-
-// type Data_settings struct {
-// ProxyList string
-// }
-//
-// type Data_tag struct {
-// Title string
-// }
-type Data_user struct {
- Title string
- User string
- Category string
- PageLimit int
- Page string
- MetaImage string
-}
-
-// add new types above this line
-// whenever you add new types, update `TestTemplates` in render_test.go to include the type in the test
-// caution: do not use pointer in Data_* struct. faker will insert nil.
-// caution: do not name template file a.b.jet.html or it won't be able to be used here, since Data_a.b is not a valid identifier.
-
-// global variable, yes.
-var views *jet.Set
-
-func InitTemplatingEngine(InDevelopment bool) {
- if InDevelopment {
- views = jet.NewSet(
- jet.NewOSFileSystemLoader("assets/views"),
- jet.InDevelopmentMode(), // disable cache
- )
- } else {
- views = jet.NewSet(
- jet.NewOSFileSystemLoader("assets/views"),
- )
- }
- for fn_name, fn := range utils.GetTemplateFunctions() {
- views.AddGlobal(fn_name, fn)
- }
-}
-
-func Render[T any](c *fiber.Ctx, data T) error {
- template_name, found := strings.CutPrefix(reflect.TypeFor[T]().Name(), "Data_")
- if !found {
- log.Panicf("struct name does not start with 'Data_': %s", template_name)
- }
-
- // Pass in values that we want to be available to all pages here
- token := session.GetPixivToken(c)
- pageURL := c.BaseURL() + c.OriginalURL()
-
- cookies := map[string]string{}
- for _, name := range session.AllCookieNames {
- value := session.GetCookie(c, name)
- cookies[string(name)] = value
- }
-
- template, err := views.GetTemplate(template_name + ".jet.html")
- if err != nil {
- return err
- }
-
- views.Parse(template_name + ".jet.html", template.String())
-
- variables := jet.VarMap{}
-
- // The middleware at line 99 in `main.go` cannot bind these values below if we use this function.
- variables.Set("BaseURL", c.BaseURL())
- variables.Set("OriginalURL", c.OriginalURL())
- variables.Set("PageURL", pageURL)
- variables.Set("LoggedIn", token != "")
- variables.Set("Queries", c.Queries())
- variables.Set("CookieList", cookies)
-
- // Type := reflect.TypeFor[T]()
- // for _, special_varname := range []string{"Title", "MetaAuthor", "MetaDescription", "MetaImage"} {
- // _, has_field := Type.FieldByName(special_varname)
- // if has_field {
- // variables.Set(special_varname, FieldName(data, special_varname))
- // }
- // }
-
- c.Context().SetContentType("text/html; charset=utf-8")
- return template.Execute(c.Response().BodyWriter(), variables, data)
-}
-
-func StructToMap[T any](data T) map[string]any {
- result := map[string]any{}
- Type := reflect.TypeFor[T]()
- for i := 0; i < Type.NumField(); i += 1 {
- field := Type.Field(i)
- result[field.Name] = FieldName(data, field.Name)
- }
- return result
-}
-
-// assumes that the field `field_name` exists, panics otherwise
-func FieldName[T any](data T, field_name string) any {
- return reflect.ValueOf(data).FieldByName(field_name).Interface()
-}
diff --git a/routes/render_test.go b/routes/render_test.go
index 7107399..843cc29 100644
--- a/routes/render_test.go
+++ b/routes/render_test.go
@@ -13,25 +13,25 @@ import (
)
func TestTemplates(t *testing.T) {
- test[Data_error](t)
- test[Data_about](t)
- test[Data_artwork](t)
- test[Data_artworkMulti](t)
- test[Data_discovery](t)
- test[Data_novelDiscovery](t)
- test[Data_index](t)
- test[Data_newest](t)
- test[Data_novel](t)
- test[Data_unauthorized](t)
- test[Data_following](t)
- test[Data_pixivisionindex](t)
- test[Data_pixivisionarticle](t)
- test[Data_rank](t)
- test[Data_rankingCalendar](t)
- test[Data_settings](t)
- test[Data_tag](t)
- test[Data_user](t)
- test[Data_userAtom](t)
+ autoTest[Data_error](t)
+ autoTest[Data_about](t)
+ autoTest[Data_artwork](t)
+ autoTest[Data_artworkMulti](t)
+ autoTest[Data_discovery](t)
+ autoTest[Data_novelDiscovery](t)
+ autoTest[Data_index](t)
+ autoTest[Data_newest](t)
+ autoTest[Data_novel](t)
+ autoTest[Data_unauthorized](t)
+ autoTest[Data_following](t)
+ autoTest[Data_pixivision_index](t)
+ autoTest[Data_pixivision_article](t)
+ autoTest[Data_rank](t)
+ autoTest[Data_rankingCalendar](t)
+ autoTest[Data_settings](t)
+ autoTest[Data_tag](t)
+ autoTest[Data_user](t)
+ autoTest[Data_userAtom](t)
}
var engine *jet.Engine
@@ -49,16 +49,19 @@ func TestMain(m *testing.M) {
m.Run()
}
-// test template
-func test[T any](t *testing.T) {
+// autoTest template with fake data
+func autoTest[T any](t *testing.T) {
var data T
faker.FakeData(&data)
+ manualTest(t, data)
+}
+func manualTest[T any](t *testing.T, data T) {
route_name, found := strings.CutPrefix(reflect.TypeFor[T]().Name(), "Data_")
if !found {
log.Panicf("struct name does not start with 'Data_': %s", route_name)
}
- bindings := StructToMap(data)
+ bindings := structToMap(data)
for k, v := range map[string]any{
"BaseURL": "",
@@ -78,4 +81,3 @@ func test[T any](t *testing.T) {
t.Errorf("while rendering template %s: %v", template_name, err)
}
}
-
diff --git a/routes/render_types.go b/routes/render_types.go
new file mode 100644
index 0000000..e6ef3a9
--- /dev/null
+++ b/routes/render_types.go
@@ -0,0 +1,120 @@
+package routes
+
+import "codeberg.org/vnpower/pixivfe/v2/core"
+
+type Data_error struct {
+ Title string
+ Error error
+}
+type Data_about struct {
+ Time string
+ Version string
+ ImageProxy string
+ AcceptLanguage string
+}
+type Data_artwork struct {
+ Illust core.Illust // faker can't fill this
+ Title string
+ MetaDescription string
+ MetaImage string
+ MetaAuthor string
+ MetaAuthorID string
+}
+type Data_artworkMulti struct {
+ Artworks []core.Illust
+ Title string
+}
+type Data_userAtom struct {
+ URL string
+ Title string
+ User core.User
+ Category core.UserArtCategory
+ Updated string
+ PageLimit int
+ Page int
+ // MetaImage string
+}
+
+type Data_index struct {
+ Title string
+ IsLoggedIn bool
+ Data core.LandingArtworks
+ NoTokenData core.Ranking
+}
+
+// below are unconverted. types may be wrong.
+type Data_discovery struct {
+ Artworks string
+ Title string
+ Queries string
+}
+type Data_novelDiscovery struct {
+ Novels string
+ Title string
+}
+type Data_newest struct {
+ Items string
+ Title string
+}
+type Data_novel struct {
+ Novel string
+ NovelRelated string
+ User string
+ Title string
+ FontType string
+ ViewMode string
+ Language string
+}
+type Data_unauthorized struct{}
+type Data_following struct {
+ Title string
+ Mode string
+ Artworks string
+ CurPage string
+ Page string
+}
+
+// type Data_pixivisionindex struct {
+// Data string
+// }
+//
+// type Data_pixivisionarticle struct {
+// Article string
+// }
+type Data_rank struct {
+ Title string
+ Page string
+ PageLimit int
+ Date string
+ Data string
+}
+type Data_rankingCalendar struct {
+ Title string
+ Render string
+ Mode string
+ Year string
+ MonthBefore string
+ MonthAfter string
+ ThisMonth string
+}
+
+// type Data_settings struct {
+// ProxyList string
+// }
+//
+// type Data_tag struct {
+// Title string
+// }
+type Data_user struct {
+ Title string
+ User string
+ Category string
+ PageLimit int
+ Page string
+ MetaImage string
+}
+
+// add new types above this line
+// whenever you add new types, update `TestTemplates` in render_test.go to include the type in the test
+// caution: do not use pointer in Data_* struct. faker will insert nil.
+// caution: do not name template file a.b.jet.html or it won't be able to be used here, since Data_a.b is not a valid identifier.