Unhardcode
This commit is contained in:
@@ -210,7 +210,7 @@ func BuildNativeWithOptions(p *project.Project, opts NativeBuildOptions, progres
|
||||
}
|
||||
var prebuiltWiki *wikiResult
|
||||
if opts.BuildWiki {
|
||||
if newestWikiSource, _, err := newestRelevantWikiSource(p.TopDataSourceDir()); err == nil && !newestWikiSource.IsZero() {
|
||||
if newestWikiSource, _, err := newestRelevantWikiSource(p); err == nil && !newestWikiSource.IsZero() {
|
||||
statePath := wikiOutputStatePath(p)
|
||||
outputDir := wikiOutputPagesDir(p)
|
||||
if stateInfo, err := os.Stat(statePath); err == nil && !newestWikiSource.After(stateInfo.ModTime()) {
|
||||
|
||||
@@ -34,6 +34,7 @@ const (
|
||||
|
||||
type DeployWikiOptions struct {
|
||||
SourceDir string
|
||||
PageIndexPath string
|
||||
Endpoint string
|
||||
Token string
|
||||
Version string
|
||||
@@ -119,9 +120,17 @@ func DeployWikiWithOptions(p *project.Project, opts DeployWikiOptions, progress
|
||||
if progress == nil {
|
||||
progress = func(string) {}
|
||||
}
|
||||
if opts.SourceDir == "" {
|
||||
sourceDirWasDefaulted := opts.SourceDir == ""
|
||||
if sourceDirWasDefaulted {
|
||||
opts.SourceDir = wikiOutputPagesDir(p)
|
||||
}
|
||||
if opts.PageIndexPath == "" {
|
||||
if sourceDirWasDefaulted {
|
||||
opts.PageIndexPath = p.TopDataWikiPageIndexPath()
|
||||
} else {
|
||||
opts.PageIndexPath = filepath.Join(filepath.Dir(opts.SourceDir), p.EffectiveConfig().TopData.Wiki.PageIndexFile)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(opts.SourceDir); err != nil {
|
||||
return deployResult{}, fmt.Errorf("wiki source directory not found: %w", err)
|
||||
}
|
||||
@@ -172,7 +181,7 @@ func DeployWikiWithOptions(p *project.Project, opts DeployWikiOptions, progress
|
||||
}
|
||||
|
||||
progress(fmt.Sprintf("Collecting local wiki pages from %s", opts.SourceDir))
|
||||
pages, err := collectLocalPages(opts.SourceDir, namespaces)
|
||||
pages, err := collectLocalPages(opts.SourceDir, opts.PageIndexPath, namespaces)
|
||||
if err != nil {
|
||||
return deployResult{}, err
|
||||
}
|
||||
@@ -377,12 +386,12 @@ func categoryIDsFromNamespaceEnv(declarations []wikiNamespaceDeclaration) (map[s
|
||||
return categories, nil
|
||||
}
|
||||
|
||||
func collectLocalPages(sourceDir string, namespaces []string) (map[string]wikiDeployPage, error) {
|
||||
func collectLocalPages(sourceDir, pageIndexPath string, namespaces []string) (map[string]wikiDeployPage, error) {
|
||||
namespaceSet := map[string]struct{}{}
|
||||
for _, namespace := range namespaces {
|
||||
namespaceSet[namespace] = struct{}{}
|
||||
}
|
||||
pageIndex, err := loadDeployPageIndex(sourceDir)
|
||||
pageIndex, err := loadDeployPageIndex(sourceDir, pageIndexPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -447,8 +456,11 @@ func collectLocalPages(sourceDir string, namespaces []string) (map[string]wikiDe
|
||||
return pages, nil
|
||||
}
|
||||
|
||||
func loadDeployPageIndex(sourceDir string) (map[string]wikiPageIndexEntry, error) {
|
||||
path := filepath.Join(filepath.Dir(sourceDir), "page-index.json")
|
||||
func loadDeployPageIndex(sourceDir, pageIndexPath string) (map[string]wikiPageIndexEntry, error) {
|
||||
path := strings.TrimSpace(pageIndexPath)
|
||||
if path == "" {
|
||||
path = filepath.Join(filepath.Dir(sourceDir), "page-index.json")
|
||||
}
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
||||
@@ -305,7 +305,7 @@ func TestCollectLocalPagesReadsGeneratedPageIDFromMarkerWhenPathIsTitleBased(t *
|
||||
t.Fatalf("write source page: %v", err)
|
||||
}
|
||||
|
||||
pages, err := collectLocalPages(sourceDir, []string{"feat"})
|
||||
pages, err := collectLocalPages(sourceDir, "", []string{"feat"})
|
||||
if err != nil {
|
||||
t.Fatalf("collectLocalPages failed: %v", err)
|
||||
}
|
||||
@@ -349,7 +349,7 @@ func TestCollectLocalPagesReadsCanonicalPublicPathFromPageIndex(t *testing.T) {
|
||||
t.Fatalf("write page index: %v", err)
|
||||
}
|
||||
|
||||
pages, err := collectLocalPages(sourceDir, []string{"spells"})
|
||||
pages, err := collectLocalPages(sourceDir, "", []string{"spells"})
|
||||
if err != nil {
|
||||
t.Fatalf("collectLocalPages failed: %v", err)
|
||||
}
|
||||
@@ -358,6 +358,44 @@ func TestCollectLocalPagesReadsCanonicalPublicPathFromPageIndex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectLocalPagesUsesConfiguredPageIndexPath(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
sourceDir := filepath.Join(root, "pages")
|
||||
if err := os.MkdirAll(filepath.Join(sourceDir, "spells"), 0755); err != nil {
|
||||
t.Fatalf("create source dir: %v", err)
|
||||
}
|
||||
generated := `<!-- sow-topdata-wiki:page=spells:acid_fog -->
|
||||
<!-- sow-topdata-wiki:managed:start hash="sha256:local" -->
|
||||
<h1>Acid Fog</h1>
|
||||
<!-- sow-topdata-wiki:managed:end -->
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(sourceDir, "spells", "Acid_Fog.html"), []byte(generated), 0644); err != nil {
|
||||
t.Fatalf("write source page: %v", err)
|
||||
}
|
||||
indexPath := filepath.Join(root, "manifest", "pages.json")
|
||||
if err := saveWikiPageIndex(indexPath, wikiPageIndex{
|
||||
Version: wikiGeneratorVersion,
|
||||
Pages: []wikiPageIndexEntry{
|
||||
{
|
||||
PageID: "spells:acid_fog",
|
||||
Title: "Acid Fog",
|
||||
PublicPath: "Magic/Acid_Fog",
|
||||
OutputPath: "pages/spells/Acid_Fog.html",
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
t.Fatalf("write page index: %v", err)
|
||||
}
|
||||
|
||||
pages, err := collectLocalPages(sourceDir, indexPath, []string{"spells"})
|
||||
if err != nil {
|
||||
t.Fatalf("collectLocalPages failed: %v", err)
|
||||
}
|
||||
if got := pages["spells:acid_fog"].PublicPath; got != "Magic/Acid_Fog" {
|
||||
t.Fatalf("expected configured page-index public path, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectLocalPagesReadsTitleFromPageIndexForHeadinglessHTML(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
sourceDir := filepath.Join(root, "pages")
|
||||
@@ -387,7 +425,7 @@ func TestCollectLocalPagesReadsTitleFromPageIndexForHeadinglessHTML(t *testing.T
|
||||
t.Fatalf("write page index: %v", err)
|
||||
}
|
||||
|
||||
pages, err := collectLocalPages(sourceDir, []string{"spells"})
|
||||
pages, err := collectLocalPages(sourceDir, "", []string{"spells"})
|
||||
if err != nil {
|
||||
t.Fatalf("collectLocalPages failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
outputDir := wikiOutputPagesDir(p)
|
||||
statePath := wikiOutputStatePath(p)
|
||||
|
||||
digest, err := computeWikiSourceDigest(p.TopDataSourceDir())
|
||||
digest, err := computeWikiSourceDigest(p)
|
||||
if err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
@@ -153,7 +153,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.templateDir = p.TopDataWikiPageTemplatesDir()
|
||||
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)
|
||||
@@ -161,7 +161,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
return wikiResult{}, err
|
||||
}
|
||||
ctx.wikiTableDefinitions = tableDefinitions
|
||||
ctx.wikiDataPath = filepath.Join(p.TopDataWikiSourceDir(), "data.yaml")
|
||||
ctx.wikiDataPath = p.TopDataWikiDataPath()
|
||||
dataProviders, err := loadWikiDataProviders(ctx.wikiDataPath)
|
||||
if err != nil {
|
||||
return wikiResult{}, err
|
||||
@@ -171,7 +171,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
if err := ctx.loadWikiVisibility(visibilityPath); err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
pageSlugOverrides, err := loadWikiPagePathDeclarations(filepath.Join(p.TopDataWikiSourceDir(), "wiki.yaml"))
|
||||
pageSlugOverrides, err := loadWikiPagePathDeclarations(p.TopDataWikiPagePathsPath())
|
||||
if err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
@@ -243,7 +243,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
if err := indexUnregisteredWikiPages(rootDir, outputDir, p.EffectiveConfig().TopData.Wiki.StalePages.Default, ctx, &pageIndex); err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
if err := saveWikiPageIndex(filepath.Join(rootDir, "page-index.json"), pageIndex); err != nil {
|
||||
if err := saveWikiPageIndex(p.TopDataWikiPageIndexPath(), pageIndex); err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
|
||||
@@ -289,8 +289,7 @@ func wikiCachedPagesAreCurrent(outputDir string, state wikiStateDocument) bool {
|
||||
|
||||
func loadWikiManualSections(p *project.Project) []wikiManualSection {
|
||||
defaults := defaultWikiManualSections()
|
||||
cfg := p.EffectiveConfig().TopData.Wiki
|
||||
path := filepath.Join(p.TopDataWikiSourceDir(), filepath.FromSlash(cfg.ManualSectionsDir), "default.yaml")
|
||||
path := p.TopDataWikiManualSectionsPath()
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return defaults
|
||||
@@ -451,9 +450,11 @@ func saveWikiState(path string, state wikiStateDocument) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func computeWikiSourceDigest(sourceDir string) (string, error) {
|
||||
func computeWikiSourceDigest(p *project.Project) (string, error) {
|
||||
hasher := sha256.New()
|
||||
_, _ = hasher.Write([]byte(wikiGeneratorVersion))
|
||||
sourceDir := p.TopDataSourceDir()
|
||||
wikiSourceDir := p.TopDataWikiSourceDir()
|
||||
files := []string{}
|
||||
relevantSourceDirs := []string{
|
||||
filepath.Join(sourceDir, "data", "feat"),
|
||||
@@ -462,7 +463,7 @@ func computeWikiSourceDigest(sourceDir string) (string, error) {
|
||||
filepath.Join(sourceDir, "data", "baseitems"),
|
||||
filepath.Join(sourceDir, "data", "classes"),
|
||||
filepath.Join(sourceDir, "data", "racialtypes"),
|
||||
filepath.Join(sourceDir, "wiki"),
|
||||
wikiSourceDir,
|
||||
}
|
||||
for _, dir := range relevantSourceDirs {
|
||||
_ = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
@@ -503,9 +504,10 @@ func computeWikiSourceDigest(sourceDir string) (string, error) {
|
||||
return fmt.Sprintf("%x", hasher.Sum(nil)), nil
|
||||
}
|
||||
|
||||
func newestRelevantWikiSource(sourceDir string) (time.Time, string, error) {
|
||||
func newestRelevantWikiSource(p *project.Project) (time.Time, string, error) {
|
||||
newest := time.Time{}
|
||||
newestPath := ""
|
||||
sourceDir := p.TopDataSourceDir()
|
||||
relevantSourceDirs := []string{
|
||||
filepath.Join(sourceDir, "data", "feat"),
|
||||
filepath.Join(sourceDir, "data", "skills"),
|
||||
@@ -513,6 +515,7 @@ func newestRelevantWikiSource(sourceDir string) (time.Time, string, error) {
|
||||
filepath.Join(sourceDir, "data", "baseitems"),
|
||||
filepath.Join(sourceDir, "data", "classes"),
|
||||
filepath.Join(sourceDir, "data", "racialtypes"),
|
||||
p.TopDataWikiSourceDir(),
|
||||
}
|
||||
for _, dir := range relevantSourceDirs {
|
||||
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project"
|
||||
)
|
||||
|
||||
func TestBuildNativeGeneratesAndSkipsWikiPages(t *testing.T) {
|
||||
@@ -98,7 +100,7 @@ func TestBuildNativeGeneratesAndSkipsWikiPages(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("read state before second build: %v", err)
|
||||
}
|
||||
digestBefore, err := computeWikiSourceDigest(filepath.Join(root, "topdata"))
|
||||
digestBefore, err := computeWikiSourceDigest(proj)
|
||||
if err != nil {
|
||||
t.Fatalf("compute digest before second build: %v", err)
|
||||
}
|
||||
@@ -1998,13 +2000,20 @@ func TestWikiSourceDigestIncludesTemplates(t *testing.T) {
|
||||
writeFile(t, filepath.Join(root, "data", "skills", "base.json"), `{"rows":[]}`+"\n")
|
||||
templatePath := filepath.Join(root, "wiki", "templates", "pages", "skills.html")
|
||||
writeFile(t, templatePath, `<h1>{{title}}</h1>`+"\n")
|
||||
proj := &project.Project{
|
||||
Root: root,
|
||||
Config: project.Config{
|
||||
Module: project.ModuleConfig{Name: "Test", ResRef: "test"},
|
||||
TopData: project.TopDataConfig{Source: ".", Wiki: project.TopDataWikiConfig{Source: "wiki"}},
|
||||
},
|
||||
}
|
||||
|
||||
before, err := computeWikiSourceDigest(root)
|
||||
before, err := computeWikiSourceDigest(proj)
|
||||
if err != nil {
|
||||
t.Fatalf("compute initial digest: %v", err)
|
||||
}
|
||||
writeFile(t, templatePath, `<h1>{{title}}</h1><p>Changed</p>`+"\n")
|
||||
after, err := computeWikiSourceDigest(root)
|
||||
after, err := computeWikiSourceDigest(proj)
|
||||
if err != nil {
|
||||
t.Fatalf("compute changed digest: %v", err)
|
||||
}
|
||||
@@ -2013,6 +2022,80 @@ func TestWikiSourceDigestIncludesTemplates(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildWikiHonorsConfiguredWikiPaths(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "skills"))
|
||||
mkdirAll(t, filepath.Join(root, "docs", "wiki", "page-fragments"))
|
||||
mkdirAll(t, filepath.Join(root, "docs", "wiki", "config"))
|
||||
mkdirAll(t, filepath.Join(root, "docs", "wiki", "sections"))
|
||||
writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "base.json"), `{
|
||||
"columns": ["Label", "Name"],
|
||||
"rows": [
|
||||
{
|
||||
"id": 0,
|
||||
"key": "skills:athletics",
|
||||
"Label": "Athletics",
|
||||
"Name": {"tlk": {"key": "skills:athletics.name", "text": "Athletics"}}
|
||||
}
|
||||
]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "lock.json"), `{"skills:athletics":0}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "page-fragments", "skills.html"), `<h1>{{title}}</h1>`+"\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "config", "providers.yaml"), "providers: {}\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "config", "paths.yaml"), "page_paths: {}\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "config", "tables.yaml"), "tables: {}\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "config", "visibility.yaml"), "datasets: {}\n")
|
||||
writeFile(t, filepath.Join(root, "docs", "wiki", "sections", "defaults.yaml"), `
|
||||
manual_sections:
|
||||
- id: user_top
|
||||
heading: Custom Top
|
||||
`)
|
||||
|
||||
statusPages := false
|
||||
proj := &project.Project{
|
||||
Root: root,
|
||||
Config: project.Config{
|
||||
Module: project.ModuleConfig{Name: "Test", ResRef: "test"},
|
||||
Paths: project.PathConfig{Build: "build", Cache: ".cache"},
|
||||
TopData: project.TopDataConfig{
|
||||
Source: "topdata",
|
||||
Build: ".cache",
|
||||
Wiki: project.TopDataWikiConfig{
|
||||
Source: "docs/wiki",
|
||||
DataFile: "config/providers.yaml",
|
||||
PagePathsFile: "config/paths.yaml",
|
||||
TablesFile: "config/tables.yaml",
|
||||
VisibilityFile: "config/visibility.yaml",
|
||||
PageTemplatesDir: "page-fragments",
|
||||
ManualSectionsFile: "sections/defaults.yaml",
|
||||
PageIndexFile: "manifest/pages.json",
|
||||
StatusPages: &statusPages,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := buildWiki(proj, BuildResult{}, true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("build wiki with configured paths: %v", err)
|
||||
}
|
||||
if result.PageCount != 1 {
|
||||
t.Fatalf("expected generated skill page, got %d", result.PageCount)
|
||||
}
|
||||
pagePath := filepath.Join(root, ".cache", "wiki", "pages", "skills", "Athletics.html")
|
||||
pageRaw, err := os.ReadFile(pagePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read configured-path wiki page: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(pageRaw), "Custom Top") {
|
||||
t.Fatalf("expected configured manual section file to be used, got:\n%s", pageRaw)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(root, ".cache", "wiki", "manifest", "pages.json")); err != nil {
|
||||
t.Fatalf("expected configured page-index file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiPageIDForKeyNormalizesSlashSeparatorsOnly(t *testing.T) {
|
||||
got := wikiPageIDForKey("feat:special/attacks_bull_rush")
|
||||
if want := "feat:special_attacks_bull_rush"; got != want {
|
||||
|
||||
Reference in New Issue
Block a user