diff --git a/.gitignore b/.gitignore index 881590c..87cd695 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /readme /replybot /include -/macro \ No newline at end of file +/macro +/recursion \ No newline at end of file diff --git a/examples/recursion/post.html b/examples/recursion/post.html new file mode 100644 index 0000000..65ed59f --- /dev/null +++ b/examples/recursion/post.html @@ -0,0 +1,6 @@ +
+

Message=#(post.Message)

+ #for(child in post.Children): + #include("post.html", post = child) + #!for +
\ No newline at end of file diff --git a/examples/recursion/recursion.go b/examples/recursion/recursion.go new file mode 100644 index 0000000..0985421 --- /dev/null +++ b/examples/recursion/recursion.go @@ -0,0 +1,80 @@ +/* + * Salix - Go templating engine + * Copyright (C) 2023 Elara Musayelyan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package main + +import ( + _ "embed" + "log" + "net/http" + + "go.elara.ws/salix" +) + +//go:embed post.html +var tmpl string + +type Post struct { + ID int + Message string + Children []*Post +} + +var posts = Post{ + ID: 0, + Message: "Hello", + Children: []*Post{ + { + ID: 12, + Message: "Hi!", + Children: []*Post{ + { + ID: 13234, + Message: "Test 2", + }, + }, + }, + { + ID: 13, + Message: "Test", + }, + }, +} + +func main() { + t, err := salix.New().ParseString("post.html", tmpl) + if err != nil { + panic(err) + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + err = t.WithVarMap(map[string]any{"post": posts}).Execute(w) + if err != nil { + log.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + }) + + log.Println("Starting HTTP server on port 8080") + + err = http.ListenAndServe(":8080", nil) + if err != nil { + log.Fatalln(err) + } +} diff --git a/salix.go b/salix.go index ea2aba4..5783300 100644 --- a/salix.go +++ b/salix.go @@ -368,6 +368,9 @@ func (t *Template) getField(fa ast.FieldAccess, local map[string]any) (any, erro return nil, err } rval := reflect.ValueOf(val) + for rval.Kind() == reflect.Pointer { + rval = rval.Elem() + } field := rval.FieldByName(fa.Name.Value) if !field.IsValid() { return nil, t.posError(fa, "%w: %s", ErrNoSuchField, fa.Name.Value) @@ -382,6 +385,9 @@ func (t *Template) execMethodCall(mc ast.MethodCall, local map[string]any) (any, return nil, err } rval := reflect.ValueOf(val) + for rval.Kind() == reflect.Pointer { + rval = rval.Elem() + } mtd := rval.MethodByName(mc.Name.Value) if !mtd.IsValid() { return nil, t.posError(mc, "%w: %s", ErrNoSuchMethod, mc.Name.Value)