Phase 1 Wiki Template refactor

This commit is contained in:
2026-05-20 13:31:27 +02:00
parent 92770bbaa0
commit 11f0863d0a
7 changed files with 580 additions and 24 deletions
+40 -24
View File
@@ -26,7 +26,7 @@ const (
legacyWikiRootDirName = ".wiki"
wikiPagesDirName = "pages"
wikiStateFileName = "state.json"
wikiGeneratorVersion = "nodebb-tiptap-html-v1"
wikiGeneratorVersion = "nodebb-tiptap-html-v2"
wikiGeneratedStatus = "generated"
wikiSkippedStatus = "skipped"
)
@@ -68,6 +68,7 @@ type wikiManualSectionsDocument struct {
type wikiManualSection struct {
ID string `json:"id" yaml:"id"`
Alias string `json:"alias" yaml:"alias"`
Heading string `json:"heading" yaml:"heading"`
Placement string `json:"placement" yaml:"placement"`
InitialHTML string `json:"initial_html" yaml:"initial_html"`
@@ -107,6 +108,8 @@ type wikiContext struct {
raceFeatTables map[string]wikiTable
statuses map[string]map[string]string
implementedFeats map[string]struct{}
manualSections []wikiManualSection
templateDir string
}
func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progress func(string)) (wikiResult, error) {
@@ -137,6 +140,9 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
if err != nil {
return wikiResult{}, err
}
manualSections := loadWikiManualSections(p)
ctx.manualSections = manualSections
ctx.templateDir = filepath.Join(p.TopDataWikiSourceDir(), filepath.FromSlash(p.EffectiveConfig().TopData.Wiki.TemplatesDir), "pages")
if err := os.RemoveAll(outputDir); err != nil {
return wikiResult{}, fmt.Errorf("clean wiki output: %w", err)
@@ -154,7 +160,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
content = renderNodeBBManagedHTML(pageID, content, loadWikiManualSections(p))
content = renderNodeBBManagedHTML(pageID, content, manualSections)
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
return err
}
@@ -182,7 +188,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
if err := generateEntityPages(outputDir, ctx, writePage); err != nil {
return wikiResult{}, err
}
if err := generateStatusPages(outputDir, pageStatuses, pageTitles, p.EffectiveConfig().TopData.Wiki.ManagedNamespaces, loadWikiManualSections(p)); err != nil {
if err := generateStatusPages(outputDir, pageStatuses, pageTitles, p.EffectiveConfig().TopData.Wiki.ManagedNamespaces, manualSections); err != nil {
return wikiResult{}, err
}
if err := indexUnregisteredWikiPages(rootDir, outputDir, p.EffectiveConfig().TopData.Wiki.StalePages.Default, &pageIndex); err != nil {
@@ -209,10 +215,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
}
func loadWikiManualSections(p *project.Project) []wikiManualSection {
defaults := []wikiManualSection{
{ID: "notes", Heading: "Notes", InitialHTML: "<h2>Notes</h2><p></p>"},
{ID: "see_also", Heading: "See Also", InitialHTML: "<h2>See Also</h2><p></p>"},
}
defaults := defaultWikiManualSections()
cfg := p.EffectiveConfig().TopData.Wiki
path := filepath.Join(p.TopDataWikiSourceDir(), filepath.FromSlash(cfg.ManualSectionsDir), "default.yaml")
raw, err := os.ReadFile(path)
@@ -229,6 +232,15 @@ func loadWikiManualSections(p *project.Project) []wikiManualSection {
if section.ID == "" {
continue
}
section.Alias = strings.TrimSpace(section.Alias)
if section.Alias == "" {
switch section.ID {
case "user_top":
section.Alias = "UserTopSection"
case "notes":
section.Alias = "UserBottomSection"
}
}
if strings.TrimSpace(section.InitialHTML) == "" {
heading := strings.TrimSpace(section.Heading)
if heading == "" {
@@ -358,13 +370,15 @@ 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"),
}
for _, dir := range relevantSourceDirs {
_ = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() {
return err
}
if strings.EqualFold(filepath.Ext(path), ".json") {
switch strings.ToLower(filepath.Ext(path)) {
case ".json", ".yaml", ".yml", ".html":
files = append(files, path)
}
return nil
@@ -760,20 +774,20 @@ func (ctx *wikiContext) shouldGeneratePage(category, key string, row map[string]
}
func (ctx *wikiContext) renderPage(category, key string, row map[string]any, title string) (string, error) {
sections := []string{
"====== " + title + " ======",
"",
buildWikiStatusBlock(ctx.pageStatus(category, key, row), category),
"",
toDokuWiki(ctx.resolveRowDescription(category, row)),
"",
ctx.renderFacts(category, key, row),
"",
ctx.renderProgression(category, row),
"",
ctx.renderRaceNameForms(row),
manualSections := ctx.manualSections
if len(manualSections) == 0 {
manualSections = defaultWikiManualSections()
}
return ensureTrailingNewline(strings.Join(sections, "\n")), nil
page := wikiTemplatePage{
PageID: wikiPageIDForKey(key),
Category: category,
Key: key,
Title: title,
Status: ctx.pageStatus(category, key, row),
Row: row,
ManualSections: manualSections,
}
return ctx.renderWikiPageTemplate(category, page)
}
func (ctx *wikiContext) renderFacts(category, key string, row map[string]any) string {
@@ -1787,11 +1801,13 @@ func renderNodeBBManagedHTML(pageID, sourceText string, manualSections []wikiMan
strings.TrimSpace(body),
"<!-- sow-topdata-wiki:managed:end -->",
}
renderedSections := extractManualRegions(body)
for _, section := range manualSections {
if _, ok := renderedSections[section.ID]; ok {
continue
}
parts = append(parts,
"<!-- sow-topdata-wiki:manual:start id=\""+html.EscapeString(section.ID)+"\" -->",
strings.TrimSpace(section.InitialHTML),
"<!-- sow-topdata-wiki:manual:end id=\""+html.EscapeString(section.ID)+"\" -->",
renderWikiManualSection(section),
)
}
return ensureTrailingNewline(strings.Join(parts, "\n"))