Alignment links

This commit is contained in:
2026-05-24 18:06:28 +02:00
parent a0c3c89049
commit 5fa5246e9f
7 changed files with 66 additions and 4 deletions
+12
View File
@@ -283,6 +283,18 @@ topdata:
value: 0
```
`topdata.wiki.alignment_links.target_pattern` controls whether formatted
alignment names become internal wiki links. The pattern may use `{alignment}`
for the title-shaped alignment segment with spaces converted to underscores, and
`{label}` for the display label:
```yaml
topdata:
wiki:
alignment_links:
target_pattern: Guides/Alignment/{alignment}
```
`paths.source` and `paths.assets` must name real repository subtrees when they
are configured. They may be omitted for repositories that do not own that class
of source, but they must not resolve to the repository root (`.`). Output and
+1
View File
@@ -256,6 +256,7 @@ func (p *Project) EffectiveConfig() EffectiveConfig {
VisibilityFile: defaultString(p.Config.TopData.Wiki.VisibilityFile, DefaultTopDataWikiVisibilityFile),
TemplatesDir: defaultString(p.Config.TopData.Wiki.TemplatesDir, DefaultTopDataWikiTemplatesDir),
ManualSectionsDir: defaultString(p.Config.TopData.Wiki.ManualSectionsDir, DefaultTopDataWikiManualSectionsDir),
AlignmentLinks: p.Config.TopData.Wiki.AlignmentLinks,
TitlePrefixMinLength: defaultInt(p.Config.TopData.Wiki.TitlePrefixMinLength, DefaultTopDataWikiTitlePrefixMinLength),
StatusPages: defaultBoolPointer(p.Config.TopData.Wiki.StatusPages, DefaultTopDataWikiStatusPages),
StatusListingScope: defaultString(p.Config.TopData.Wiki.StatusListingScope, DefaultTopDataWikiStatusListingScope),
+5
View File
@@ -249,6 +249,7 @@ type TopDataWikiConfig struct {
VisibilityFile string `json:"visibility_file" yaml:"visibility_file"`
TemplatesDir string `json:"templates_dir" yaml:"templates_dir"`
ManualSectionsDir string `json:"manual_sections_dir" yaml:"manual_sections_dir"`
AlignmentLinks TopDataWikiAlignmentLinks `json:"alignment_links" yaml:"alignment_links"`
TitlePrefixMinLength int `json:"title_prefix_min_length" yaml:"title_prefix_min_length"`
StatusPages *bool `json:"status_pages,omitempty" yaml:"status_pages,omitempty"`
StatusListingScope string `json:"status_listing_scope" yaml:"status_listing_scope"`
@@ -256,6 +257,10 @@ type TopDataWikiConfig struct {
ManagedRegion TopDataWikiManagedRegionConfig `json:"managed_region" yaml:"managed_region"`
}
type TopDataWikiAlignmentLinks struct {
TargetPattern string `json:"target_pattern" yaml:"target_pattern"`
}
type TopDataWikiStalePagesConfig struct {
Default string `json:"default" yaml:"default"`
LiveCleanup string `json:"live_cleanup" yaml:"live_cleanup"`
+2
View File
@@ -120,6 +120,7 @@ type wikiContext struct {
visibleWikiKeys map[string]bool
namespaceTitles map[string]string
namespacePaths map[string]string
alignmentLinkPattern string
}
func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progress func(string)) (wikiResult, error) {
@@ -153,6 +154,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
manualSections := loadWikiManualSections(p)
ctx.manualSections = manualSections
ctx.templateDir = filepath.Join(p.TopDataWikiSourceDir(), filepath.FromSlash(p.EffectiveConfig().TopData.Wiki.TemplatesDir), "pages")
ctx.alignmentLinkPattern = p.EffectiveConfig().TopData.Wiki.AlignmentLinks.TargetPattern
ctx.wikiTablesPath = filepath.Join(p.TopDataWikiSourceDir(), filepath.FromSlash(p.EffectiveConfig().TopData.Wiki.TablesFile))
tableDefinitions, err := loadWikiTableDefinitions(ctx.wikiTablesPath)
if err != nil {
+22
View File
@@ -1288,6 +1288,28 @@ func TestWikiTemplateFormatsPreferredAlignments(t *testing.T) {
}
}
func TestWikiTemplateFormatsPreferredAlignmentsWithConfiguredLinks(t *testing.T) {
ctx := &wikiContext{alignmentLinkPattern: "Guides/Alignment/{alignment}"}
page := wikiTemplatePage{
PageID: "racialtypes:tiefling",
Category: "racialtypes",
Key: "racialtypes:tiefling",
Title: "Tiefling",
Row: map[string]any{
"PreferredAlignments": map[string]any{"list": []any{"le", "ne", "ce"}},
},
}
got, err := ctx.renderWikiTemplateString("racialtypes.html", `{{alignments(PreferredAlignments)}}`, page)
if err != nil {
t.Fatalf("render template: %v", err)
}
want := "[[Guides/Alignment/Lawful_Evil|Lawful Evil]], [[Guides/Alignment/Neutral_Evil|Neutral Evil]], [[Guides/Alignment/Chaotic_Evil|Chaotic Evil]]"
if got != want {
t.Fatalf("expected %q, got %q", want, got)
}
}
func TestWikiTemplateDescriptionFiltersExtractParagraphsAndSections(t *testing.T) {
ctx := &wikiContext{}
page := wikiTemplatePage{
+1 -1
View File
@@ -1059,7 +1059,7 @@ func (p *wikiExprParser) callHelper(name string, args []any) (any, error) {
if len(args) != 1 {
return nil, fmt.Errorf("alignments expects 1 argument")
}
return formatWikiTemplateAlignments(args[0])
return p.ctx.formatWikiTemplateAlignments(args[0])
case "ability_adjustments":
if len(args) != 0 {
return nil, fmt.Errorf("ability_adjustments expects 0 arguments")
+23 -3
View File
@@ -188,7 +188,7 @@ func (ctx *wikiContext) applyWikiTemplateFilter(value any, filter string, state
case "count":
return countWikiTemplateValue(value), nil
case "alignments":
return formatWikiTemplateAlignments(value)
return ctx.formatWikiTemplateAlignments(value)
case "list":
return wikiTemplateHTML(renderWikiTemplateList(value, firstArg(args))), nil
case "ordinal":
@@ -367,7 +367,7 @@ func joinWikiTemplateValue(value any, sep string) string {
}
}
func formatWikiTemplateAlignments(value any) (string, error) {
func (ctx *wikiContext) formatWikiTemplateAlignments(value any) (string, error) {
values, err := wikiTemplateAlignmentValues(value)
if err != nil {
return "", err
@@ -384,7 +384,7 @@ func formatWikiTemplateAlignments(value any) (string, error) {
if !ok {
return "", fmt.Errorf("unknown alignment value 0x%02X", value)
}
labels = append(labels, label)
labels = append(labels, ctx.renderWikiTemplateAlignmentLabel(label))
}
if len(labels) == 0 {
return "Any", nil
@@ -392,6 +392,26 @@ func formatWikiTemplateAlignments(value any) (string, error) {
return strings.Join(labels, ", "), nil
}
func (ctx *wikiContext) renderWikiTemplateAlignmentLabel(label string) string {
pattern := ""
if ctx != nil {
pattern = strings.TrimSpace(ctx.alignmentLinkPattern)
}
if pattern == "" {
return label
}
target := strings.ReplaceAll(pattern, "{alignment}", wikiTemplateAlignmentTargetSegment(label))
target = strings.ReplaceAll(target, "{label}", label)
if strings.TrimSpace(target) == "" {
return label
}
return "[[" + target + "|" + label + "]]"
}
func wikiTemplateAlignmentTargetSegment(label string) string {
return strings.ReplaceAll(strings.TrimSpace(label), " ", "_")
}
func wikiTemplateAlignmentValues(value any) ([]int, error) {
if isNullLike(value) {
return []int{0}, nil