summaryrefslogtreecommitdiff
path: root/internal/build/build.go
blob: 743942be7078236208837d111fe04b6cfd799baa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package build

import (
	"fmt"
	"html/template"
	"log"
	"time"

	"github.com/HimanshuSardana/kite/pkg/content"
	"github.com/HimanshuSardana/kite/pkg/themes"
)

const (
	DefaultContentDir = "./content"
	DefaultOutputDir  = "./output"
	DefaultThemesDir  = "./themes"
	DefaultConfigPath = "./config.yaml"
	DefaultThemeName  = "modern-light"
)

type BuildOptions struct {
	ThemeName  string
	ContentDir string
	OutputDir  string
	ThemesDir  string
	ConfigPath string
}

func Build(opts BuildOptions) error {
	if opts.ThemeName == "" {
		opts.ThemeName = DefaultThemeName
	}
	if opts.ContentDir == "" {
		opts.ContentDir = DefaultContentDir
	}
	if opts.OutputDir == "" {
		opts.OutputDir = DefaultOutputDir
	}
	if opts.ThemesDir == "" {
		opts.ThemesDir = DefaultThemesDir
	}
	if opts.ConfigPath == "" {
		opts.ConfigPath = DefaultConfigPath
	}

	themePath := themes.GetThemePath(opts.ThemesDir, opts.ThemeName)

	files, err := content.ListContentFiles(opts.ContentDir)
	if err != nil {
		return fmt.Errorf("listing content files: %w", err)
	}

	summaries := make([]content.PostSummary, 0, len(files))

	for _, file := range files {
		fmt.Println("Processing:", file.Path)

		parsed, err := ParseMarkdown(file.Path)
		if err != nil {
			log.Printf("Error parsing %s: %v", file.Path, err)
			continue
		}

		summaries = append(summaries, content.PostSummary{
			Title: parsed.Frontmatter.Title,
			Slug:  file.Slug,
			Date:  parsed.Frontmatter.Date,
			Tags:  parsed.Frontmatter.Tags,
		})

		outputPath, err := content.GetOutputPath(opts.ContentDir, file.Path, opts.OutputDir)
		if err != nil {
			log.Printf("Error computing output path: %v", err)
			continue
		}

		tmpl, err := LoadTemplate(themePath, "layout.html")
		if err != nil {
			log.Fatalf("Error loading template: %v", err)
		}

		page := Page{
			Title:   parsed.Frontmatter.Title,
			Content: template.HTML(parsed.Content),
			TOC:     parsed.TOC,
			Year:    time.Now().Year(),
		}

		if err := RenderPage(tmpl, outputPath, page); err != nil {
			log.Printf("Error rendering page: %v", err)
		}
	}

	fmt.Println("All files processed!")

	if err := RenderHomePage(themePath, opts.OutputDir, opts.ConfigPath, summaries); err != nil {
		log.Printf("Error rendering home page: %v", err)
	}

	return nil
}

func ListThemes(themesDir string) []string {
	if themesDir == "" {
		themesDir = DefaultThemesDir
	}

	themeList, err := themes.List(themesDir)
	if err != nil {
		log.Fatal("Error:", err)
	}

	result := make([]string, len(themeList))
	for i, t := range themeList {
		result[i] = t.Name
	}
	return result
}

func ShowHelpMessage() {
	fmt.Println(`
Kite — A lightweight static site generator

USAGE:
  kite <command> [options]

COMMANDS:
  build         Build the static site into the output directory
  serve         Start a local development server with live reload
  list-themes   List all available themes

OPTIONS:
  -h, --help    Show this help message

EXAMPLES:
  kite build
  kite serve
  kite serve --port 8080
  kite list-themes

DESCRIPTION:
  Kite converts your content into a static website using themes and templates.
  Use 'build' for production output and 'serve' for local development.
`)
}