package main import ( "fmt" "html/template" "io/ioutil" "os" "path/filepath" "strings" "time" "github.com/russross/blackfriday/v2" ) // NavItem represents a link in the navigation menu type NavItem struct { Title string URL string } func main() { contentDir := "./content" outputDir := "./public" templateFile := "./templates/layout.html" tpl, err := parseTemplate(templateFile) if err != nil { fmt.Printf("Template parsing error: %v\n", err) return } files, err := readContentFiles(contentDir) if err != nil { fmt.Printf("Failed to read content directory: %v\n", err) return } nav := buildNavigation(files) for _, file := range files { if filepath.Ext(file.Name()) == ".md" { err := generateHTML(file, contentDir, outputDir, tpl, nav) if err != nil { fmt.Printf("Error generating HTML for %s: %v\n", file.Name(), err) } } } fmt.Println("✅ Site generation complete.") } func parseTemplate(templateFile string) (*template.Template, error) { return template.ParseFiles(templateFile) } func readContentFiles(contentDir string) ([]os.FileInfo, error) { return ioutil.ReadDir(contentDir) } func buildNavigation(files []os.FileInfo) []NavItem { var nav []NavItem for _, file := range files { if filepath.Ext(file.Name()) == ".md" { name := strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())) title := strings.Title(name) url := "/" if name != "index" { url = "/" + name + "/" } nav = append(nav, NavItem{Title: title, URL: url}) } } return nav } func generateHTML(file os.FileInfo, contentDir, outputDir string, tpl *template.Template, nav []NavItem) error { name := strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())) title := strings.Title(name) mdPath := filepath.Join(contentDir, file.Name()) mdContent, err := ioutil.ReadFile(mdPath) if err != nil { return fmt.Errorf("failed to read %s: %w", file.Name(), err) } htmlContent := blackfriday.Run(mdContent) var outPath string if name == "index" { outPath = filepath.Join(outputDir, "index.html") } else { subDir := filepath.Join(outputDir, name) os.MkdirAll(subDir, os.ModePerm) outPath = filepath.Join(subDir, "index.html") } outFile, err := os.Create(outPath) if err != nil { return fmt.Errorf("failed to create %s: %w", outPath, err) } defer outFile.Close() data := map[string]interface{}{ "Content": template.HTML(htmlContent), "Title": title, "Nav": nav, "Year": time.Now().Year(), "Date": time.Now().Format("January 2, 2006"), } return tpl.Execute(outFile, data) }