Canonical path adherence (#10)
Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/10 Co-authored-by: vickydotbat <vickydotbat@tutamail.com> Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
@@ -56,8 +56,7 @@ type wikiPageIndexEntry struct {
|
||||
SourceDataset string `json:"source_dataset"`
|
||||
SourceKey string `json:"source_key"`
|
||||
Title string `json:"title"`
|
||||
PublicSlug string `json:"public_slug"`
|
||||
PublicTarget string `json:"public_target"`
|
||||
PublicPath string `json:"public_path"`
|
||||
Hash string `json:"hash"`
|
||||
OutputPath string `json:"output_path"`
|
||||
EditPolicy string `json:"edit_policy"`
|
||||
@@ -119,7 +118,7 @@ type wikiContext struct {
|
||||
wikiDataProviders map[string]wikiDataProviderDefinition
|
||||
visibilityPolicy *wikiVisibilityDefinitions
|
||||
visibleWikiKeys map[string]bool
|
||||
pageSlugOverrides map[string]string
|
||||
namespaceTitles map[string]string
|
||||
}
|
||||
|
||||
func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progress func(string)) (wikiResult, error) {
|
||||
@@ -173,7 +172,12 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
if err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
ctx.pageSlugOverrides = pageSlugOverrides
|
||||
_ = pageSlugOverrides
|
||||
namespaceDeclarations, err := loadWikiNamespaceDeclarations(p)
|
||||
if err != nil {
|
||||
return wikiResult{}, err
|
||||
}
|
||||
ctx.namespaceTitles = wikiNamespaceTitles(namespaceDeclarations)
|
||||
|
||||
if err := os.RemoveAll(outputDir); err != nil {
|
||||
return wikiResult{}, fmt.Errorf("clean wiki output: %w", err)
|
||||
@@ -192,8 +196,8 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
return err
|
||||
}
|
||||
namespace := strings.SplitN(pageID, ":", 2)[0]
|
||||
publicSlug := ctx.publicWikiPageSlug(pageID, title)
|
||||
content = renderNodeBBManagedHTML(pageID, publicSlug, content, manualSections)
|
||||
publicPath := ctx.publicWikiPath(namespace, title)
|
||||
content = renderNodeBBManagedHTML(pageID, content, manualSections)
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -209,8 +213,7 @@ func buildWiki(p *project.Project, nativeResult BuildResult, force bool, progres
|
||||
SourceDataset: categoryFromWikiNamespace(namespace),
|
||||
SourceKey: pageID,
|
||||
Title: title,
|
||||
PublicSlug: publicSlug,
|
||||
PublicTarget: wikiPublicTarget(namespace, publicSlug),
|
||||
PublicPath: publicPath,
|
||||
Hash: computeManagedHash(content),
|
||||
OutputPath: filepath.ToSlash(rel),
|
||||
EditPolicy: wikiEditPolicy(namespace),
|
||||
@@ -327,7 +330,7 @@ func saveWikiPageIndex(path string, index wikiPageIndex) error {
|
||||
func validateWikiPageIndex(index wikiPageIndex) error {
|
||||
pageIDs := map[string]string{}
|
||||
outputPaths := map[string]string{}
|
||||
publicTargets := map[string]string{}
|
||||
publicPaths := map[string]string{}
|
||||
for _, entry := range index.Pages {
|
||||
if previous, ok := pageIDs[entry.PageID]; ok {
|
||||
return fmt.Errorf("duplicate wiki page-index page_id %q for %s and %s", entry.PageID, previous, entry.OutputPath)
|
||||
@@ -335,11 +338,11 @@ func validateWikiPageIndex(index wikiPageIndex) error {
|
||||
if previous, ok := outputPaths[entry.OutputPath]; ok {
|
||||
return fmt.Errorf("duplicate wiki page-index output_path %q for %s and %s", entry.OutputPath, previous, entry.PageID)
|
||||
}
|
||||
if entry.PublicTarget != "" {
|
||||
if previous, ok := publicTargets[entry.PublicTarget]; ok {
|
||||
return fmt.Errorf("duplicate wiki page-index public_target %q for %s and %s", entry.PublicTarget, previous, entry.PageID)
|
||||
if entry.PublicPath != "" {
|
||||
if previous, ok := publicPaths[entry.PublicPath]; ok {
|
||||
return fmt.Errorf("duplicate wiki page-index public_path %q for %s and %s", entry.PublicPath, previous, entry.PageID)
|
||||
}
|
||||
publicTargets[entry.PublicTarget] = entry.PageID
|
||||
publicPaths[entry.PublicPath] = entry.PageID
|
||||
}
|
||||
pageIDs[entry.PageID] = entry.OutputPath
|
||||
outputPaths[entry.OutputPath] = entry.PageID
|
||||
@@ -383,8 +386,7 @@ func indexUnregisteredWikiPages(rootDir, outputDir, stalePolicy string, index *w
|
||||
SourceDataset: categoryFromWikiNamespace(namespace),
|
||||
SourceKey: pageID,
|
||||
Title: extractHTMLTitle(string(raw), pageID),
|
||||
PublicSlug: wikiSlugifyTitle(extractHTMLTitle(string(raw), pageID)),
|
||||
PublicTarget: wikiPublicTarget(namespace, wikiSlugifyTitle(extractHTMLTitle(string(raw), pageID))),
|
||||
PublicPath: (&wikiContext{}).publicWikiPath(namespace, extractHTMLTitle(string(raw), pageID)),
|
||||
Hash: computeManagedHash(string(raw)),
|
||||
OutputPath: filepath.ToSlash(relToRoot),
|
||||
EditPolicy: wikiEditPolicy(namespace),
|
||||
@@ -1532,7 +1534,7 @@ func writeWikiFile(path, content string, manualSections []wikiManualSection) err
|
||||
return err
|
||||
}
|
||||
pageID := wikiRelPathToPageID(path)
|
||||
content = renderNodeBBManagedHTML(pageID, wikiSlugifyTitle(extractHTMLTitle(content, pageID)), content, manualSections)
|
||||
content = renderNodeBBManagedHTML(pageID, content, manualSections)
|
||||
return os.WriteFile(path, []byte(ensureTrailingNewline(content)), 0o644)
|
||||
}
|
||||
|
||||
@@ -1636,6 +1638,18 @@ func filterWikiPageIDs(pageStatuses map[string]string, namespace, status string)
|
||||
return pageIDs
|
||||
}
|
||||
|
||||
func wikiNamespaceTitles(declarations []wikiNamespaceDeclaration) map[string]string {
|
||||
titles := map[string]string{}
|
||||
for _, declaration := range declarations {
|
||||
id := strings.TrimSpace(declaration.ID)
|
||||
title := strings.TrimSpace(declaration.Title)
|
||||
if id != "" && title != "" {
|
||||
titles[id] = title
|
||||
}
|
||||
}
|
||||
return titles
|
||||
}
|
||||
|
||||
func wikiPageIDForKey(key string) string {
|
||||
if key == "" {
|
||||
return ""
|
||||
@@ -1655,17 +1669,10 @@ func wikiPageIDForKey(key string) string {
|
||||
if namespace == "" {
|
||||
return ""
|
||||
}
|
||||
value = strings.NewReplacer("/", ":", "\\", ":", "_", ":").Replace(value)
|
||||
value = strings.NewReplacer("/", ":", "\\", ":").Replace(value)
|
||||
return namespace + ":" + value
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) publicWikiPageSlug(pageID, title string) string {
|
||||
if slug := ctx.pageSlugOverrides[pageID]; slug != "" {
|
||||
return slug
|
||||
}
|
||||
return wikiSlugifyTitle(title)
|
||||
}
|
||||
|
||||
func (ctx *wikiContext) publicWikiTargetForKey(key, fallbackTitle string) string {
|
||||
pageID := wikiPageIDForKey(key)
|
||||
if pageID == "" {
|
||||
@@ -1683,19 +1690,21 @@ func (ctx *wikiContext) publicWikiTargetForKey(key, fallbackTitle string) string
|
||||
title = key
|
||||
}
|
||||
namespace := strings.SplitN(pageID, ":", 2)[0]
|
||||
return wikiPublicTarget(namespace, ctx.publicWikiPageSlug(pageID, title))
|
||||
return ctx.publicWikiPath(namespace, title)
|
||||
}
|
||||
|
||||
func wikiPublicTarget(namespace, slug string) string {
|
||||
namespace = strings.TrimSpace(namespace)
|
||||
slug = strings.TrimSpace(slug)
|
||||
if namespace == "" {
|
||||
return slug
|
||||
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
|
||||
}
|
||||
}
|
||||
if slug == "" {
|
||||
return namespace
|
||||
segments := []string{namespaceTitle}
|
||||
for _, part := range strings.Split(title, " :: ") {
|
||||
segments = append(segments, part)
|
||||
}
|
||||
return namespace + "/" + slug
|
||||
return canonicalWikiPath(segments...)
|
||||
}
|
||||
|
||||
func wikiSlugifyTitle(value string) string {
|
||||
@@ -1719,7 +1728,9 @@ func wikiRelPathToPageID(path string) string {
|
||||
func namespaceTitle(namespace string) string {
|
||||
switch namespace {
|
||||
case "itemtypes":
|
||||
return "Itemtypes"
|
||||
return "Item Types"
|
||||
case "feat":
|
||||
return "Feats"
|
||||
default:
|
||||
return strings.Title(namespace)
|
||||
}
|
||||
@@ -1924,14 +1935,14 @@ func renderNodeBBManagedMarkdown(pageID, dokuText string) string {
|
||||
return ensureTrailingNewline(strings.Join(parts, "\n"))
|
||||
}
|
||||
|
||||
func renderNodeBBManagedHTML(pageID, publicSlug, sourceText string, manualSections []wikiManualSection) string {
|
||||
func renderNodeBBManagedHTML(pageID, sourceText string, manualSections []wikiManualSection) string {
|
||||
body := sourceText
|
||||
if !strings.Contains(sourceText, "<h1") {
|
||||
body = dokuWikiToNodeBBHTML(sourceText)
|
||||
}
|
||||
hash := computeManagedHash(body)
|
||||
parts := []string{
|
||||
"<!-- sow-topdata-wiki:page=" + pageID + " wiki_slug=" + publicSlug + " -->",
|
||||
"<!-- sow-topdata-wiki:page=" + pageID + " -->",
|
||||
"<!-- sow-topdata-wiki:managed:start hash=\"sha256:" + hash + "\" -->",
|
||||
strings.TrimSpace(body),
|
||||
"<!-- sow-topdata-wiki:managed:end -->",
|
||||
|
||||
Reference in New Issue
Block a user