Reject a folder using the reference prefix, and filter bindings only where they exist

This commit is contained in:
Mikael Göransson
2026-08-28 00:08:58 +02:00
committed by lilleman-tw
parent 095a7f2de5
commit 2d8fcae4f4
2 changed files with 14 additions and 2 deletions
+3
View File
@@ -55,6 +55,9 @@ func loadDir(dir string) (*group, error) {
for _, e := range entries { for _, e := range entries {
full := filepath.Join(dir, e.Name()) full := filepath.Join(dir, e.Name())
if e.IsDir() { if e.IsDir() {
if isRef(e.Name()) {
return nil, fmt.Errorf("%s: folder %q starts with %q, which is reserved for {..path} bindings", full, e.Name(), refPrefix)
}
child, err := loadDir(full) child, err := loadDir(full)
if err != nil { if err != nil {
return nil, err return nil, err
+11 -2
View File
@@ -75,7 +75,7 @@ type namedNode struct {
func contained(n node) []namedNode { func contained(n node) []namedNode {
switch n := n.(type) { switch n := n.(type) {
case *group: case *group:
return named(n.children) return authored(n.children)
case *choice: case *choice:
out := make([]namedNode, len(n.items)) out := make([]namedNode, len(n.items))
for i, it := range n.items { for i, it := range n.items {
@@ -90,7 +90,8 @@ func contained(n node) []namedNode {
} }
// named skips a bound {..path} key: it is a render edge, not containment, so using // named skips a bound {..path} key: it is a render edge, not containment, so using
// it as a path segment would report a node under a path that does not reach it. // it as a path segment would report a node under a path that does not reach it. Only
// a template's fields hold bindings, so group children go through authored.
func named(m map[string]node) []namedNode { func named(m map[string]node) []namedNode {
out := make([]namedNode, 0, len(m)) out := make([]namedNode, 0, len(m))
for _, name := range sortedNames(m) { for _, name := range sortedNames(m) {
@@ -102,6 +103,14 @@ func named(m map[string]node) []namedNode {
return out return out
} }
func authored(m map[string]node) []namedNode {
out := make([]namedNode, 0, len(m))
for _, name := range sortedNames(m) {
out = append(out, namedNode{name: name, node: m[name]})
}
return out
}
func sortedNames(m map[string]node) []string { func sortedNames(m map[string]node) []string {
names := make([]string, 0, len(m)) names := make([]string, 0, len(m))
for name := range m { for name := range m {