From 153f46fbc81a662a5eccfc6ea97085e8b3c565f4 Mon Sep 17 00:00:00 2001 From: vickydotbat Date: Sun, 24 May 2026 09:45:57 +0200 Subject: [PATCH] Fix race pages deploy --- internal/topdata/wiki_native.go | 47 +++++++++++++++--- internal/topdata/wiki_native_test.go | 74 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/internal/topdata/wiki_native.go b/internal/topdata/wiki_native.go index 8a1e932..0dd39a3 100644 --- a/internal/topdata/wiki_native.go +++ b/internal/topdata/wiki_native.go @@ -552,11 +552,11 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) { } } + datasets, err := discoverNativeDatasets(dataDir) + if err != nil { + return nil, err + } loadBase := func(name string) (nativeCollectedDataset, bool, error) { - datasets, err := discoverNativeDatasets(dataDir) - if err != nil { - return nativeCollectedDataset{}, false, err - } for _, dataset := range datasets { if dataset.Name == name { collected, err := collectNativeDataset(dataset) @@ -590,7 +590,7 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) { if err != nil { return nil, err } - raceDatasets, err := collectRacialtypesRegistryDatasets(dataDir) + raceDatasets, err := collectWikiRacialtypesDatasets(dataDir, datasets) if err != nil { return nil, err } @@ -602,12 +602,16 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) { raceRows, raceIDToKey = rowsByKeyAndID(dataset.Rows) continue } - raceFeatTables[outputStem(dataset.Dataset.OutputName)] = wikiTable{ + table := wikiTable{ Key: dataset.TableKey, Output: dataset.Dataset.OutputName, OutputStem: outputStem(dataset.Dataset.OutputName), Rows: cloneRows(dataset.Rows), } + raceFeatTables[table.OutputStem] = table + if table.Key != "" { + raceFeatTables[table.Key] = table + } } classFeatTables, err := loadWikiTables(filepath.Join(dataDir, "classes", "feats")) @@ -689,11 +693,40 @@ func loadWikiContext(dataDir, sourceDir string) (*wikiContext, error) { if classOK { ctx.statuses["classes"] = collectDatasetStatuses(filepath.Join(dataDir, "classes", "core"), "classes/core") } - ctx.statuses["racialtypes"] = collectRaceStatuses(filepath.Join(dataDir, "racialtypes", "registry")) + ctx.statuses["racialtypes"] = collectWikiRacialtypeStatuses(dataDir) ctx.implementedFeats = ctx.collectImplementedFeatKeys() return ctx, nil } +func collectWikiRacialtypesDatasets(dataDir string, datasets []nativeDataset) ([]nativeCollectedDataset, error) { + out := []nativeCollectedDataset{} + for _, dataset := range datasets { + name := filepath.ToSlash(dataset.Name) + if !strings.HasPrefix(name, "racialtypes/") { + continue + } + collected, err := collectNativeDataset(dataset) + if err != nil { + return nil, err + } + if collected.Dataset.OutputName == "racialtypes.2da" || collected.TableKey != "" { + out = append(out, collected) + } + } + if len(out) > 0 { + return out, nil + } + return collectRacialtypesRegistryDatasets(dataDir) +} + +func collectWikiRacialtypeStatuses(dataDir string) map[string]string { + coreRoot := filepath.Join(dataDir, "racialtypes", "core") + if _, err := os.Stat(coreRoot); err == nil { + return collectDatasetStatuses(coreRoot, "racialtypes/core") + } + return collectRaceStatuses(filepath.Join(dataDir, "racialtypes", "registry")) +} + func rowsByKeyAndID(rows []map[string]any) (map[string]map[string]any, map[int]string) { byKey := map[string]map[string]any{} byID := map[int]string{} diff --git a/internal/topdata/wiki_native_test.go b/internal/topdata/wiki_native_test.go index 5da8f9d..459e2c6 100644 --- a/internal/topdata/wiki_native_test.go +++ b/internal/topdata/wiki_native_test.go @@ -364,6 +364,80 @@ func TestBuildNativeCanDisableWikiStatusPages(t *testing.T) { } } +func TestBuildNativeWikiGeneratesRacePagesFromCoreRacialtypes(t *testing.T) { + root := testProjectRoot(t) + mkdirAll(t, filepath.Join(root, "topdata", "data", "feat")) + mkdirAll(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "modules")) + mkdirAll(t, filepath.Join(root, "topdata", "data", "racialtypes", "00_feats")) + writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n") + writeFile(t, filepath.Join(root, "topdata", "data", "feat", "base.json"), `{ + "output": "feat.2da", + "columns": ["FEAT", "DESCRIPTION"], + "rows": [ + {"id": 10, "key": "feat:darkvision", "FEAT": "Darkvision", "DESCRIPTION": "See in the dark."} + ] +}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "feat", "lock.json"), `{"feat:darkvision":10}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "base.json"), `{ + "output": "racialtypes.2da", + "columns": ["Label", "Name", "Description", "Appearance", "PlayerRace", "FeatsTable"], + "rows": [ + {"id": 7, "key": "racialtypes:beast", "Label": "Beast", "Name": "Beast", "Description": "Creature category.", "Appearance": 174, "PlayerRace": 0, "FeatsTable": "****"} + ] +}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "lock.json"), `{"racialtypes:beast":7,"racialtypes:goblin_dynamic":39}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "modules", "add_goblin.json"), `{ + "entries": { + "racialtypes:goblin_dynamic": { + "Label": "Goblin_Dynamic", + "Name": {"tlk": {"text": "Goblin"}}, + "Description": {"tlk": {"text": "A playable goblin race."}}, + "Appearance": 15381, + "PlayerRace": 1, + "FeatsTable": {"table": "racialtypes/feats:goblin_dynamic"} + } + } +}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "racialtypes", "00_feats", "goblin.json"), `{ + "key": "racialtypes/feats:goblin_dynamic", + "output": "race_feat_gobpc.2da", + "columns": ["FeatLabel", "FeatIndex"], + "rows": [ + {"id": 0, "FeatIndex": {"id": "feat:darkvision"}} + ] +}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "racialtypes", "00_feats", "lock.json"), "{}\n") + + disabled := false + proj := testProject(root) + proj.Config.TopData.ReferenceBuilder = "" + proj.Config.TopData.Wiki.StatusPages = &disabled + + result, err := BuildNative(proj, nil) + if err != nil { + t.Fatalf("BuildNative failed: %v", err) + } + if result.WikiPages != 2 { + t.Fatalf("expected one generated race page and its referenced feat page, got %d", result.WikiPages) + } + pagePath := filepath.Join(root, ".cache", "wiki", "pages", "races", "Goblin.html") + got, err := os.ReadFile(pagePath) + if err != nil { + t.Fatalf("read generated race page: %v", err) + } + if !strings.Contains(string(got), "A playable goblin race.") || !strings.Contains(string(got), "[[Feats/Darkvision|Darkvision]]") { + t.Fatalf("expected generated race page content, got:\n%s", got) + } + indexRaw, err := os.ReadFile(filepath.Join(root, ".cache", "wiki", "page-index.json")) + if err != nil { + t.Fatalf("read page index: %v", err) + } + indexText := string(indexRaw) + if !strings.Contains(indexText, `"page_id": "races:goblin_dynamic"`) || !strings.Contains(indexText, `"namespace": "races"`) || !strings.Contains(indexText, `"public_path": "Races/Goblin"`) { + t.Fatalf("expected generated race page-index entry, got:\n%s", indexText) + } +} + func countGeneratedWikiHTMLFiles(t *testing.T, root string) int { t.Helper() count := 0