Replay each path's selectors through the walk for the family fence, require a key for a name, refuse a name shadowing a key, a table reading its own family and an ancestor's column clash, add the row node and family.go, and pin eight rows inline
Tests / vet + fmt + tests (pull_request) Successful in 1m8s
Tests / Gitea release from CHANGELOG.md (pull_request) Has been skipped

This commit is contained in:
2026-09-17 12:54:24 +02:00
parent fb83aa6178
commit 047237f361
14 changed files with 419 additions and 277 deletions
+19
View File
@@ -109,6 +109,9 @@ func linkTemplateRefs(folder []string, path, category string, t *template, root
if category != "" && key == "/"+category {
return fmt.Errorf("%s: reference {%s}: names the category it sits in; read a sibling field as a path, or move the shared value into its own category and reference that", path, name)
}
if err := checkNotOwnFamily(root, category, target); err != nil {
return fmt.Errorf("%s: reference {%s}: %w", path, name, err)
}
if err := checkPath(target, tail, key); err != nil {
return fmt.Errorf("%s: reference {%s}: %w", path, name, err)
}
@@ -122,6 +125,22 @@ func linkTemplateRefs(folder []string, path, category string, t *template, root
return nil
}
// checkNotOwnFamily refuses a reference from a table's format or cell into a table of
// its own family: a table rendered whole draws its row without pinning it, so the
// family would draw apart from the row being rendered.
func checkNotOwnFamily(root map[string]node, category string, target node) error {
if category == "" {
return nil
}
_, own, _, err := resolveCategory(root, strings.Split(category, "."))
from, isTable := own.(*table)
into, targetIsTable := target.(*table)
if err != nil || !isTable || !targetIsTable || from.family() != into.family() {
return nil
}
return fmt.Errorf("a cell or format of %s reads %s, a table of its own family, which a row of %s rendered whole would draw apart from; read the family from a template beside it, or add the value as a column", from.category, into.category, from.category)
}
// columnRead is a record's column read by a format of that one reference alone, which is the
// column: it takes the column's datatype and null.
type columnRead struct {