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.
`)
}
|