Class wiki page refactors

This commit is contained in:
2026-05-27 09:50:22 +02:00
parent fd83d96c3a
commit bd9d2c6da0
2 changed files with 289 additions and 0 deletions
+175
View File
@@ -686,6 +686,151 @@ func (ctx *wikiContext) classFeatRows(classRow map[string]any) []map[string]any
return out
}
func (ctx *wikiContext) classProficiencyLinks(classRow map[string]any) []string {
rows := ctx.classFilteredFeatLinks(classRow, func(row map[string]any, key, name string) bool {
level, err := asInt(fieldValue(row, "GrantedOnLevel"))
if err != nil || level != 1 {
return false
}
text := strings.ToLower(key + " " + name)
return strings.Contains(text, "proficiency")
})
return rows
}
func (ctx *wikiContext) classSelectableFeatLinks(classRow map[string]any) []string {
return ctx.classFilteredFeatLinks(classRow, func(row map[string]any, key, name string) bool {
list, err := asInt(fieldValue(row, "List"))
return err == nil && (list == 1 || list == 2)
})
}
func (ctx *wikiContext) classFilteredFeatLinks(classRow map[string]any, keep func(row map[string]any, key, name string) bool) []string {
table := ctx.tableForValue(fieldValue(classRow, "FeatsTable"), ctx.classFeatTables)
if table == nil {
return nil
}
out := []string{}
seen := map[string]struct{}{}
for _, source := range table.Rows {
key := resolveReferenceKey(fieldValue(source, "FeatIndex"), ctx.featIDToKey)
if key == "" {
key = resolveReferenceKey(fieldValue(source, "FeatIndex"), nil)
}
if key == "" {
continue
}
name := ctx.resolveFeatName(key)
if !keep(source, key, name) {
continue
}
link := ctx.renderReference(map[string]any{"id": key}, nil, ctx.resolveFeatName)
if link == "" {
continue
}
if _, ok := seen[link]; ok {
continue
}
seen[link] = struct{}{}
out = append(out, link)
}
return out
}
func (ctx *wikiContext) classSaveSummary(classRow map[string]any) string {
table := ctx.tableForValue(fieldValue(classRow, "SavingThrowTable"), ctx.classSaveTables)
if table == nil {
return ""
}
var levelOne map[string]any
for _, row := range table.Rows {
level, err := asInt(fieldValue(row, "Level"))
if err == nil && level == 1 {
levelOne = row
break
}
}
if levelOne == nil {
return ""
}
high := []string{}
for _, save := range []struct {
field string
label string
}{
{"FortSave", "Fortitude"},
{"RefSave", "Reflex"},
{"WillSave", "Will"},
} {
value, err := asInt(fieldValue(levelOne, save.field))
if err == nil && value > 0 {
high = append(high, save.label)
}
}
if len(high) == 0 {
return "Low"
}
return "High " + formatWikiEnglishList(high)
}
func classBABLabel(table string) string {
switch strings.ToLower(strings.TrimSpace(table)) {
case "cls_atk_1", "atk_1":
return "+1/1"
case "cls_atk_2", "atk_2":
return "+3/4"
case "cls_atk_3", "atk_3":
return "+1/2"
default:
return ""
}
}
func wikiAbilityName(value string) string {
switch strings.ToUpper(strings.TrimSpace(value)) {
case "STR":
return "Strength"
case "DEX":
return "Dexterity"
case "CON":
return "Constitution"
case "INT":
return "Intelligence"
case "WIS":
return "Wisdom"
case "CHA":
return "Charisma"
default:
return strings.TrimSpace(value)
}
}
func wikiIndefiniteArticle(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return "a"
}
switch strings.ToLower(value[:1]) {
case "a", "e", "i", "o", "u":
return "an"
default:
return "a"
}
}
func formatWikiEnglishList(values []string) string {
switch len(values) {
case 0:
return ""
case 1:
return values[0]
case 2:
return values[0] + " and " + values[1]
default:
return strings.Join(values[:len(values)-1], ", ") + ", and " + values[len(values)-1]
}
}
func (ctx *wikiContext) classSummaryRows(classRow map[string]any) []map[string]any {
return []map[string]any{
{"Label": "Hit Die", "Value": "d" + stringValue(classRow, "HitDie")},
@@ -1373,6 +1518,36 @@ func (p *wikiExprParser) callHelper(name string, args []any) (any, error) {
return nil, fmt.Errorf("ability_adjustments expects 0 arguments")
}
return formatAbilityAdjustments(p.renderCtx.Page.Row), nil
case "ability_name":
if len(args) != 1 {
return nil, fmt.Errorf("ability_name expects 1 argument")
}
return wikiAbilityName(stringifyWikiTableValue(args[0])), nil
case "indefinite_article":
if len(args) != 1 {
return nil, fmt.Errorf("indefinite_article expects 1 argument")
}
return wikiIndefiniteArticle(stringifyWikiTableValue(args[0])), nil
case "class_bab":
if len(args) != 0 {
return nil, fmt.Errorf("class_bab expects 0 arguments")
}
return classBABLabel(stringValue(p.renderCtx.Page.Row, "AttackBonusTable")), nil
case "class_proficiencies":
if len(args) != 0 {
return nil, fmt.Errorf("class_proficiencies expects 0 arguments")
}
return p.ctx.classProficiencyLinks(p.renderCtx.Page.Row), nil
case "class_saves":
if len(args) != 0 {
return nil, fmt.Errorf("class_saves expects 0 arguments")
}
return p.ctx.classSaveSummary(p.renderCtx.Page.Row), nil
case "class_selectable_feats":
if len(args) != 0 {
return nil, fmt.Errorf("class_selectable_feats expects 0 arguments")
}
return p.ctx.classSelectableFeatLinks(p.renderCtx.Page.Row), nil
case "hidden_ref":
if len(args) != 2 {
return nil, fmt.Errorf("hidden_ref expects 2 arguments")