Files
sow-tools/internal/topdata/wiki_page_paths.go

78 lines
2.0 KiB
Go

package topdata
import (
"fmt"
"os"
"strings"
"gopkg.in/yaml.v3"
)
type wikiPagePathDocument struct {
PagePaths wikiPagePaths `json:"page_paths" yaml:"page_paths"`
}
type wikiPagePaths struct {
SlugOverrides []wikiPageSlugOverride `json:"slug_overrides" yaml:"slug_overrides"`
}
type wikiPageSlugOverride struct {
PageID string `json:"page_id" yaml:"page_id"`
Slug string `json:"slug" yaml:"slug"`
}
func loadWikiPagePathDeclarations(path string) (map[string]string, error) {
raw, err := os.ReadFile(path)
if os.IsNotExist(err) {
return map[string]string{}, nil
}
if err != nil {
return nil, err
}
return parseWikiPagePathDeclarations(raw, path)
}
func parseWikiPagePathDeclarations(raw []byte, path string) (map[string]string, error) {
var doc wikiPagePathDocument
if err := yaml.Unmarshal(raw, &doc); err != nil {
return nil, fmt.Errorf("parse wiki page paths %s: %w", path, err)
}
if len(doc.PagePaths.SlugOverrides) > 0 {
return nil, fmt.Errorf("parse wiki page paths %s: page_paths.slug_overrides is retired; generated public wiki paths are title-derived", path)
}
overrides := map[string]string{}
for _, override := range doc.PagePaths.SlugOverrides {
pageID := strings.TrimSpace(override.PageID)
slug := strings.TrimSpace(override.Slug)
if pageID == "" {
return nil, fmt.Errorf("parse wiki page paths %s: slug override has empty page_id", path)
}
if !isCanonicalWikiSlug(slug) {
return nil, fmt.Errorf("parse wiki page paths %s: page_id %q has invalid slug %q", path, pageID, override.Slug)
}
if _, ok := overrides[pageID]; ok {
return nil, fmt.Errorf("parse wiki page paths %s: duplicate page_id %q", path, pageID)
}
overrides[pageID] = slug
}
return overrides, nil
}
func isCanonicalWikiSlug(value string) bool {
if value == "" || value != strings.ToLower(value) {
return false
}
parts := strings.Split(value, "-")
for _, part := range parts {
if part == "" {
return false
}
for _, r := range part {
if !((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9')) {
return false
}
}
}
return true
}