Add configurable topdata wiki visibility policy (#4)

## Summary
- add YAML-backed generated wiki visibility policies for topdata datasets
- centralize page and reference eligibility through a visibility index
- cover eligibility helpers, metadata precedence, derived feat sets, and link suppression with toolkit tests

## Verification
- go test ./...
- module ./validate-topdata.sh with the feature toolkit binary
- module ./build-wiki.sh --force with the feature toolkit binary

Companion module branch: codex-wiki-visibility.

Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/4
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
2026-05-21 13:45:06 +02:00
committed by archvillainette
parent 499d7773cd
commit 057ed19276
8 changed files with 779 additions and 6 deletions
+56 -5
View File
@@ -607,11 +607,12 @@ func tokenizeWikiExpr(expr string) []wikiExprToken {
}
type wikiExprParser struct {
tokens []wikiExprToken
pos int
row map[string]any
ctx *wikiContext
renderCtx wikiTableRenderContext
tokens []wikiExprToken
pos int
row map[string]any
ctx *wikiContext
renderCtx wikiTableRenderContext
allowMissingFields bool
}
func (p *wikiExprParser) peek() wikiExprToken {
@@ -771,12 +772,21 @@ func (p *wikiExprParser) resolveField(name string) (any, error) {
if name == "HasSpellProgression" {
return hasSpellProgression(p.renderCtx.Page.Row), nil
}
switch name {
case "true":
return true, nil
case "false":
return false, nil
}
if value, ok := lookupField(p.row, name); ok {
return value, nil
}
if value, ok := lookupField(p.renderCtx.Page.Row, name); ok {
return value, nil
}
if p.allowMissingFields {
return nil, nil
}
return nil, fmt.Errorf("missing field %q", name)
}
@@ -800,6 +810,9 @@ func (p *wikiExprParser) callHelper(name string, args []any) (any, error) {
case "link":
if len(args) == 1 {
key := stringifyWikiTableValue(args[0])
if p.ctx != nil && !p.ctx.canReferenceWikiKey(key) {
return "", nil
}
if pageID := wikiPageIDForKey(key); pageID != "" {
key = pageID
}
@@ -811,6 +824,9 @@ func (p *wikiExprParser) callHelper(name string, args []any) (any, error) {
if key == "" {
return label, nil
}
if p.ctx != nil && !p.ctx.canReferenceWikiKey(key) {
return "", nil
}
if pageID := wikiPageIDForKey(key); pageID != "" {
key = pageID
}
@@ -870,11 +886,46 @@ func (p *wikiExprParser) callHelper(name string, args []any) (any, error) {
return args[1], nil
}
return args[0], nil
case "present":
if len(args) != 1 {
return nil, fmt.Errorf("present expects 1 argument")
}
return presentWikiValue(args[0]), nil
case "all_present":
if len(args) == 0 {
return nil, fmt.Errorf("all_present expects at least 1 argument")
}
for _, value := range args {
if !presentWikiValue(value) {
return false, nil
}
}
return true, nil
case "any_present":
if len(args) == 0 {
return nil, fmt.Errorf("any_present expects at least 1 argument")
}
for _, value := range args {
if presentWikiValue(value) {
return true, nil
}
}
return false, nil
default:
return nil, fmt.Errorf("unknown helper %q", name)
}
}
func presentWikiValue(value any) bool {
if isNullLike(value) {
return false
}
if text, ok := value.(string); ok {
return strings.TrimSpace(text) != ""
}
return value != nil
}
func ordinalWikiTableValue(value int) string {
suffix := "th"
if value%100 < 11 || value%100 > 13 {