// filesystem.go package main import ( "fmt" "io/fs" "os" "path/filepath" "sort" "strings" "time" ) // ContentFile represents a discoverable file in the content directory type ContentFile struct { OriginalPath string RoutePath string IsMarkdown bool ModTime time.Time } // RouteMap is our lookup table: Route -> File Info type RouteMap map[string]ContentFile // Global list for the index generator var AllContent []ContentFile // ScanContent walks the content directory and builds the routing map. func ScanContent(rootDir string) (RouteMap, error) { routes := make(RouteMap) var contentList []ContentFile fmt.Println("--- Scanning Content ---") err := filepath.WalkDir(rootDir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } // Skip root and hidden files if path == rootDir || strings.HasPrefix(d.Name(), ".") { return nil } if !d.IsDir() { info, err := d.Info() if err != nil { return err } relPath, _ := filepath.Rel(rootDir, path) relPath = filepath.ToSlash(relPath) isMd := strings.HasSuffix(strings.ToLower(d.Name()), ".md") // Determine Route var route string if isMd { route = "/" + strings.TrimSuffix(relPath, filepath.Ext(relPath)) if strings.ToLower(route) == "/index" { route = "/" } } else { route = "/" + relPath } // Normalize to lowercase for case-insensitive URLs route = strings.ToLower(route) file := ContentFile{ OriginalPath: path, RoutePath: route, IsMarkdown: isMd, ModTime: info.ModTime(), } // Add to Lookup Map routes[route] = file // Add to List (for index generation) contentList = append(contentList, file) fmt.Printf("Mapped: %s -> %s\n", route, path) } return nil }) if err != nil { return nil, err } // Sort list by date sort.Slice(contentList, func(i, j int) bool { return contentList[i].ModTime.After(contentList[j].ModTime) }) AllContent = contentList return routes, nil } // ReadRaw reads the file from the filesystem. func ReadRaw(path string) ([]byte, error) { return os.ReadFile(path) }