Align topdata wiki canonical paths (#11)
Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/11 Co-authored-by: Michał Piasecki <mpiasecki720@protonmail.com> Co-committed-by: Michał Piasecki <mpiasecki720@protonmail.com>
This commit is contained in:
@@ -119,6 +119,7 @@ type wikiContext struct {
|
||||
visibilityPolicy *wikiVisibilityDefinitions
|
||||
visibleWikiKeys map[string]bool
|
||||
namespaceTitles map[string]string
|
||||
namespacePaths map[string]string
|
||||
}
|
||||
|
||||
func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progress func(string)) (wikiResult, error) {
|
||||
@@ -178,6 +179,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
return wikiResult{}, err
|
||||
}
|
||||
ctx.namespaceTitles = wikiNamespaceTitles(namespaceDeclarations)
|
||||
ctx.namespacePaths = wikiNamespacePaths(namespaceDeclarations)
|
||||
|
||||
if err := os.RemoveAll(outputDir); err != nil {
|
||||
return wikiResult{}, fmt.Errorf("clean wiki output: %w", err)
|
||||
@@ -231,10 +233,10 @@ 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, p.EffectiveConfig().TopData.Wiki.StatusListingScope, manualSections); err != nil {
|
||||
if err := generateStatusPages(outputDir, pageStatuses, pageTitles, p.EffectiveConfig().TopData.Wiki.ManagedNamespaces, p.EffectiveConfig().TopData.Wiki.StatusListingScope, manualSections, ctx); err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
if err := indexUnregisteredWikiPages(rootDir, outputDir, p.EffectiveConfig().TopData.Wiki.StalePages.Default, &pageIndex); err != nil {
|
||||
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 {
|
||||
@@ -345,10 +347,14 @@ func validateWikiPageIndex(index wikiPageIndex) error {
|
||||
return fmt.Errorf("duplicate wiki page-index output_path %q for %s and %s", entry.OutputPath, previous, entry.PageID)
|
||||
}
|
||||
if entry.PublicPath != "" {
|
||||
if previous, ok := publicPaths[entry.PublicPath]; ok {
|
||||
publicPathKey := canonicalWikiSlashPathFoldedKey(entry.PublicPath)
|
||||
if publicPathKey == "" {
|
||||
publicPathKey = entry.PublicPath
|
||||
}
|
||||
if previous, ok := publicPaths[publicPathKey]; ok {
|
||||
return fmt.Errorf("duplicate wiki page-index public_path %q for %s and %s", entry.PublicPath, previous, entry.PageID)
|
||||
}
|
||||
publicPaths[entry.PublicPath] = entry.PageID
|
||||
publicPaths[publicPathKey] = entry.PageID
|
||||
}
|
||||
pageIDs[entry.PageID] = entry.OutputPath
|
||||
outputPaths[entry.OutputPath] = entry.PageID
|
||||
@@ -356,11 +362,14 @@ func validateWikiPageIndex(index wikiPageIndex) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func indexUnregisteredWikiPages(rootDir, outputDir, stalePolicy string, index *wikiPageIndex) error {
|
||||
func indexUnregisteredWikiPages(rootDir, outputDir, stalePolicy string, ctx *wikiContext, index *wikiPageIndex) error {
|
||||
seen := map[string]struct{}{}
|
||||
for _, entry := range index.Pages {
|
||||
seen[entry.PageID] = struct{}{}
|
||||
}
|
||||
if ctx == nil {
|
||||
ctx = &wikiContext{}
|
||||
}
|
||||
return filepath.WalkDir(outputDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -389,13 +398,14 @@ func indexUnregisteredWikiPages(rootDir, outputDir, stalePolicy string, index *w
|
||||
if err != nil {
|
||||
relToRoot = filepath.Base(path)
|
||||
}
|
||||
title := extractHTMLTitle(string(raw), pageID)
|
||||
index.Pages = append(index.Pages, wikiPageIndexEntry{
|
||||
PageID: pageID,
|
||||
Namespace: namespace,
|
||||
SourceDataset: categoryFromWikiNamespace(namespace),
|
||||
SourceKey: pageID,
|
||||
Title: extractHTMLTitle(string(raw), pageID),
|
||||
PublicPath: (&wikiContext{}).publicWikiPath(namespace, extractHTMLTitle(string(raw), pageID)),
|
||||
Title: title,
|
||||
PublicPath: ctx.publicWikiPath(namespace, title),
|
||||
Hash: computeManagedHash(string(raw)),
|
||||
OutputPath: filepath.ToSlash(relToRoot),
|
||||
EditPolicy: wikiEditPolicy(namespace),
|
||||
@@ -1507,19 +1517,19 @@ func wikiStatusNoun(category string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func generateStatusPages(outputDir string, pageStatuses map[string]string, pageTitles map[string]string, namespaces []string, listingScope string, manualSections []wikiManualSection) error {
|
||||
func generateStatusPages(outputDir string, pageStatuses map[string]string, pageTitles map[string]string, namespaces []string, listingScope string, manualSections []wikiManualSection, ctx *wikiContext) error {
|
||||
summaries := buildWikiNamespaceSummaries(pageStatuses, namespaces)
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus.html"), renderWikiStatusReportPage(summaries, namespaces), manualSections); err != nil {
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus.html"), renderWikiStatusReportPage(summaries, namespaces, ctx), manualSections); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, namespace := range namespaces {
|
||||
summary := summaries[namespace]
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", namespace+".html"), renderWikiNamespaceFragment(namespace, summary), manualSections); err != nil {
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", namespace+".html"), renderWikiNamespaceFragment(namespace, summary, ctx), manualSections); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, status := range []string{wikiStatusNew, wikiStatusModified, wikiStatusVanilla} {
|
||||
pageIDs := filterWikiPageIDs(pageStatuses, namespace, status)
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", namespace, status+".html"), renderWikiStatusListingPage(namespaceTitle(namespace)+" "+wikiStatusLabels[status]+" Pages", pageIDs, pageTitles), manualSections); err != nil {
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", namespace, status+".html"), renderWikiStatusListingPage(wikiNamespacePublicTitle(ctx, namespace)+" "+wikiStatusLabels[status]+" Pages", pageIDs, pageTitles, ctx), manualSections); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -1530,7 +1540,7 @@ func generateStatusPages(outputDir string, pageStatuses map[string]string, pageT
|
||||
if listingScope == "all" {
|
||||
for _, status := range []string{wikiStatusNew, wikiStatusModified, wikiStatusVanilla} {
|
||||
pageIDs := filterWikiPageIDs(pageStatuses, "", status)
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", status+".html"), renderWikiStatusListingPage(wikiStatusLabels[status]+" Pages", pageIDs, pageTitles), manualSections); err != nil {
|
||||
if err := writeWikiFile(filepath.Join(outputDir, "meta", "wikistatus", status+".html"), renderWikiStatusListingPage(wikiStatusLabels[status]+" Pages", pageIDs, pageTitles, ctx), manualSections); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -1587,20 +1597,36 @@ func rollupWikiStatuses(statuses []string) string {
|
||||
return best
|
||||
}
|
||||
|
||||
func renderWikiNamespaceFragment(namespace string, summary map[string]any) string {
|
||||
return renderStatusTable(namespaceTitle(namespace), summary, "")
|
||||
func wikiNamespacePublicTitle(ctx *wikiContext, namespace string) string {
|
||||
if ctx != nil && ctx.namespaceTitles != nil {
|
||||
if declared := strings.TrimSpace(ctx.namespaceTitles[namespace]); declared != "" {
|
||||
return declared
|
||||
}
|
||||
}
|
||||
return namespaceTitle(namespace)
|
||||
}
|
||||
|
||||
func renderWikiStatusReportPage(summaries map[string]map[string]any, namespaces []string) string {
|
||||
func renderWikiNamespaceFragment(namespace string, summary map[string]any, ctx *wikiContext) string {
|
||||
return renderStatusTable(wikiNamespacePublicTitle(ctx, namespace), summary, "")
|
||||
}
|
||||
|
||||
func renderWikiStatusReportPage(summaries map[string]map[string]any, namespaces []string, ctx *wikiContext) string {
|
||||
if ctx == nil {
|
||||
ctx = &wikiContext{}
|
||||
}
|
||||
lines := []string{"====== Wiki Status ======", "", "This page is auto-generated from builder source provenance.", ""}
|
||||
for _, namespace := range namespaces {
|
||||
summary := summaries[namespace]
|
||||
lines = append(lines, renderStatusTable(namespaceTitle(namespace), summary, fmt.Sprintf("[[%s:index|%s]]", namespace, namespaceTitle(namespace))))
|
||||
title := wikiNamespacePublicTitle(ctx, namespace)
|
||||
lines = append(lines, renderStatusTable(title, summary, fmt.Sprintf("[[%s|%s]]", ctx.publicWikiPath(namespace, ""), title)))
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func renderWikiStatusListingPage(title string, pageIDs []string, pageTitles map[string]string) string {
|
||||
func renderWikiStatusListingPage(title string, pageIDs []string, pageTitles map[string]string, ctx *wikiContext) string {
|
||||
if ctx == nil {
|
||||
ctx = &wikiContext{}
|
||||
}
|
||||
lines := []string{"====== " + title + " ======", ""}
|
||||
if len(pageIDs) == 0 {
|
||||
lines = append(lines, "No matching generated pages.")
|
||||
@@ -1610,7 +1636,8 @@ func renderWikiStatusListingPage(title string, pageIDs []string, pageTitles map[
|
||||
if title == "" {
|
||||
title = pageID
|
||||
}
|
||||
lines = append(lines, " * [["+pageID+"|"+title+"]]")
|
||||
namespace := strings.SplitN(pageID, ":", 2)[0]
|
||||
lines = append(lines, " * [["+ctx.publicWikiPath(namespace, title)+"|"+title+"]]")
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
@@ -1659,6 +1686,18 @@ func wikiNamespaceTitles(declarations []wikiNamespaceDeclaration) map[string]str
|
||||
return titles
|
||||
}
|
||||
|
||||
func wikiNamespacePaths(declarations []wikiNamespaceDeclaration) map[string]string {
|
||||
paths := map[string]string{}
|
||||
for _, declaration := range declarations {
|
||||
id := strings.TrimSpace(declaration.ID)
|
||||
path := strings.TrimSpace(declaration.CanonicalPath)
|
||||
if id != "" && path != "" {
|
||||
paths[id] = path
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func wikiPageIDForKey(key string) string {
|
||||
if key == "" {
|
||||
return ""
|
||||
@@ -1703,17 +1742,37 @@ func (ctx *wikiContext) publicWikiTargetForKey(key, fallbackTitle string) string
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) publicWikiPath(namespace, title string) string {
|
||||
namespaceTitle := namespaceTitle(namespace)
|
||||
if ctx != nil && ctx.namespaceTitles != nil {
|
||||
if declared := strings.TrimSpace(ctx.namespaceTitles[namespace]); declared != "" {
|
||||
namespaceTitle = declared
|
||||
namespacePath := canonicalWikiSegment(namespaceTitle(namespace))
|
||||
if ctx != nil && ctx.namespacePaths != nil {
|
||||
if declared := strings.TrimSpace(ctx.namespacePaths[namespace]); declared != "" {
|
||||
namespacePath = declared
|
||||
}
|
||||
}
|
||||
segments := []string{namespaceTitle}
|
||||
for _, part := range strings.Split(title, " :: ") {
|
||||
segments = append(segments, part)
|
||||
if ctx != nil && ctx.namespaceTitles != nil && (ctx.namespacePaths == nil || strings.TrimSpace(ctx.namespacePaths[namespace]) == "") {
|
||||
if declared := strings.TrimSpace(ctx.namespaceTitles[namespace]); declared != "" {
|
||||
namespacePath = canonicalWikiSegment(declared)
|
||||
}
|
||||
}
|
||||
return canonicalWikiPath(segments...)
|
||||
titlePath := canonicalWikiPath(wikiTitlePathParts(title)...)
|
||||
switch {
|
||||
case namespacePath == "":
|
||||
return titlePath
|
||||
case titlePath == "":
|
||||
return namespacePath
|
||||
default:
|
||||
return namespacePath + "/" + titlePath
|
||||
}
|
||||
}
|
||||
|
||||
func wikiTitlePathParts(title string) []string {
|
||||
parts := []string{}
|
||||
for _, part := range strings.Split(title, "::") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
parts = append(parts, part)
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
func wikiSlugifyTitle(value string) string {
|
||||
@@ -1726,9 +1785,7 @@ func wikiPageOutputRelPath(pageID, title string) string {
|
||||
namespace = "page"
|
||||
}
|
||||
parts := []string{namespace}
|
||||
for _, part := range strings.Split(title, " :: ") {
|
||||
parts = append(parts, part)
|
||||
}
|
||||
parts = append(parts, wikiTitlePathParts(title)...)
|
||||
path := canonicalWikiPath(parts...)
|
||||
if path == "" {
|
||||
path = wikiPageIDToRelPath(pageID)
|
||||
|
||||
Reference in New Issue
Block a user