- Add theme configuration to WebServer struct - Create default theme with base.html layout template - Update content.go to apply theme templates to generated HTML - Output is now full HTML documents with styling Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
133 lines
3.2 KiB
Go
133 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/yuin/goldmark"
|
|
)
|
|
|
|
// ContentFile represents a parsed content file
|
|
type ContentFile struct {
|
|
SourcePath string // Original .md file path
|
|
Name string // File name without extension
|
|
Content string // Raw markdown content
|
|
HTML string // Converted HTML
|
|
}
|
|
|
|
// PageData represents data passed to the template
|
|
type PageData struct {
|
|
Title string
|
|
Content template.HTML
|
|
}
|
|
|
|
// generateOutput reads content from ./content, processes it, and writes to ./output
|
|
func generateOutput() error {
|
|
// Ensure content directory exists
|
|
if _, err := os.Stat(contentPath); os.IsNotExist(err) {
|
|
return fmt.Errorf("content directory does not exist: %s", contentPath)
|
|
}
|
|
|
|
// Ensure output directory exists
|
|
if err := os.MkdirAll(outputPath, 0755); err != nil {
|
|
return fmt.Errorf("failed to create output directory: %w", err)
|
|
}
|
|
|
|
// Load the theme template
|
|
themePath := filepath.Join("themes", ws.Theme, "base.html")
|
|
tmpl, err := template.ParseFiles(themePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load theme template %s: %w", themePath, err)
|
|
}
|
|
|
|
// Read all markdown files from content directory
|
|
files, err := readContentFiles()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read content files: %w", err)
|
|
}
|
|
|
|
if len(files) == 0 {
|
|
fmt.Println("Warning: No markdown files found in content directory")
|
|
return nil
|
|
}
|
|
|
|
// Process each file
|
|
for _, file := range files {
|
|
fmt.Printf("Processing: %s\n", file.SourcePath)
|
|
|
|
// Convert markdown to HTML
|
|
html, err := markdownToHTML(file.Content)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to convert %s: %w", file.SourcePath, err)
|
|
}
|
|
file.HTML = html
|
|
|
|
// Apply theme template
|
|
var output bytes.Buffer
|
|
data := PageData{
|
|
Title: file.Name + " - " + ws.AppName,
|
|
Content: template.HTML(file.HTML),
|
|
}
|
|
if err := tmpl.Execute(&output, data); err != nil {
|
|
return fmt.Errorf("failed to execute template for %s: %w", file.SourcePath, err)
|
|
}
|
|
|
|
// Write output
|
|
outputFile := filepath.Join(outputPath, file.Name+".html")
|
|
if err := os.WriteFile(outputFile, output.Bytes(), 0644); err != nil {
|
|
return fmt.Errorf("failed to write %s: %w", outputFile, err)
|
|
}
|
|
fmt.Printf(" -> Written: %s\n", outputFile)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// readContentFiles reads all .md files from the content directory
|
|
func readContentFiles() ([]ContentFile, error) {
|
|
var files []ContentFile
|
|
|
|
entries, err := os.ReadDir(contentPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
continue
|
|
}
|
|
|
|
name := entry.Name()
|
|
if !strings.HasSuffix(name, ".md") {
|
|
continue
|
|
}
|
|
|
|
fullPath := filepath.Join(contentPath, name)
|
|
content, err := os.ReadFile(fullPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read %s: %w", fullPath, err)
|
|
}
|
|
|
|
files = append(files, ContentFile{
|
|
SourcePath: fullPath,
|
|
Name: strings.TrimSuffix(name, ".md"),
|
|
Content: string(content),
|
|
})
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
|
|
// markdownToHTML converts markdown content to HTML using goldmark
|
|
func markdownToHTML(markdown string) (string, error) {
|
|
var buf bytes.Buffer
|
|
if err := goldmark.Convert([]byte(markdown), &buf); err != nil {
|
|
return "", err
|
|
}
|
|
return buf.String(), nil
|
|
}
|