blog/filesystem.go

105 lines
2.1 KiB
Go

// 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)
}