summaryrefslogtreecommitdiff
path: root/internal/build
diff options
context:
space:
mode:
Diffstat (limited to 'internal/build')
-rw-r--r--internal/build/build.go19
-rw-r--r--internal/build/rss.go129
2 files changed, 147 insertions, 1 deletions
diff --git a/internal/build/build.go b/internal/build/build.go
index 743942b..721b568 100644
--- a/internal/build/build.go
+++ b/internal/build/build.go
@@ -6,6 +6,7 @@ import (
"log"
"time"
+ "github.com/HimanshuSardana/kite/pkg/config"
"github.com/HimanshuSardana/kite/pkg/content"
"github.com/HimanshuSardana/kite/pkg/themes"
)
@@ -43,6 +44,11 @@ func Build(opts BuildOptions) error {
opts.ConfigPath = DefaultConfigPath
}
+ cfg, err := config.Load(opts.ConfigPath)
+ if err != nil {
+ log.Printf("Warning: Could not load config: %v", err)
+ }
+
themePath := themes.GetThemePath(opts.ThemesDir, opts.ThemeName)
files, err := content.ListContentFiles(opts.ContentDir)
@@ -53,7 +59,7 @@ func Build(opts BuildOptions) error {
summaries := make([]content.PostSummary, 0, len(files))
for _, file := range files {
- fmt.Println("Processing:", file.Path)
+ start := time.Now()
parsed, err := ParseMarkdown(file.Path)
if err != nil {
@@ -89,6 +95,9 @@ func Build(opts BuildOptions) error {
if err := RenderPage(tmpl, outputPath, page); err != nil {
log.Printf("Error rendering page: %v", err)
}
+
+ elapsed := time.Since(start).Milliseconds()
+ fmt.Printf("Compiling %s (%dms)\n", parsed.Frontmatter.Title, elapsed)
}
fmt.Println("All files processed!")
@@ -97,6 +106,14 @@ func Build(opts BuildOptions) error {
log.Printf("Error rendering home page: %v", err)
}
+ siteURL := "https://your-site.com"
+ if cfg != nil && cfg.SiteURL != "" {
+ siteURL = cfg.SiteURL
+ }
+ if err := GenerateRSS(opts.OutputDir, opts.ConfigPath, siteURL, summaries); err != nil {
+ log.Printf("Error generating RSS feed: %v", err)
+ }
+
return nil
}
diff --git a/internal/build/rss.go b/internal/build/rss.go
new file mode 100644
index 0000000..ad22615
--- /dev/null
+++ b/internal/build/rss.go
@@ -0,0 +1,129 @@
+package build
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "github.com/HimanshuSardana/kite/pkg/config"
+ "github.com/HimanshuSardana/kite/pkg/content"
+)
+
+type RSSItem struct {
+ Title string
+ Link string
+ Date string
+ Content string
+}
+
+type RSSFeed struct {
+ Title string
+ Link string
+ Description string
+ Items []RSSItem
+}
+
+func GenerateRSS(outputDir, configPath, siteURL string, posts []content.PostSummary) error {
+ if configPath == "" {
+ configPath = "config.yaml"
+ }
+
+ cfg, err := config.Load(configPath)
+ if err != nil {
+ return fmt.Errorf("loading config: %w", err)
+ }
+
+ feed := RSSFeed{
+ Title: cfg.SiteTitle,
+ Link: siteURL,
+ Description: cfg.AuthorBio,
+ Items: make([]RSSItem, 0, len(posts)),
+ }
+
+ for _, post := range posts {
+ dateStr := post.Date
+ var pubDate time.Time
+
+ if t, err := time.Parse("2006-01-02", post.Date); err == nil {
+ pubDate = t
+ dateStr = pubDate.Format(time.RFC1123)
+ } else if t, err := time.Parse("Jan 2006", post.Date); err == nil {
+ pubDate = t
+ dateStr = pubDate.Format(time.RFC1123)
+ }
+
+ feed.Items = append(feed.Items, RSSItem{
+ Title: post.Title,
+ Link: fmt.Sprintf("%s/%s/", siteURL, post.Slug),
+ Date: dateStr,
+ Content: fmt.Sprintf("Read more at %s/%s/", siteURL, post.Slug),
+ })
+ }
+
+ rssContent := renderRSS(feed)
+
+ feedPath := "feed.xml"
+ if outputDir != "" && outputDir != "." {
+ feedPath = outputDir + "/feed.xml"
+ }
+
+ if err := os.WriteFile(feedPath, []byte(rssContent), 0644); err != nil {
+ return fmt.Errorf("writing feed: %w", err)
+ }
+
+ fmt.Println("Feed written to", feedPath)
+ return nil
+}
+
+func renderRSS(feed RSSFeed) string {
+ updated := time.Now().Format(time.RFC1123)
+
+ s := `<?xml version="1.0" encoding="UTF-8"?>
+<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+ <channel>
+ <title>` + escapeXML(feed.Title) + `</title>
+ <link>` + escapeXML(feed.Link) + `</link>
+ <description>` + escapeXML(feed.Description) + `</description>
+ <language>en-us</language>
+ <lastBuildDate>` + updated + `</lastBuildDate>
+ <atom:link href="` + escapeXML(feed.Link) + `/feed.xml" rel="self" type="application/rss+xml"/>
+`
+
+ for _, item := range feed.Items {
+ s += ` <item>
+ <title>` + escapeXML(item.Title) + `</title>
+ <link>` + escapeXML(item.Link) + `</link>
+ <guid>` + escapeXML(item.Link) + `</guid>
+ <pubDate>` + item.Date + `</pubDate>
+ <description>` + escapeXML(item.Content) + `</description>
+ </item>
+`
+ }
+
+ s += ` </channel>
+</rss>`
+
+ return s
+}
+
+func escapeXML(s string) string {
+ s = replaceAll(s, "&", "&amp;")
+ s = replaceAll(s, "<", "&lt;")
+ s = replaceAll(s, ">", "&gt;")
+ s = replaceAll(s, "\"", "&quot;")
+ s = replaceAll(s, "'", "&apos;")
+ return s
+}
+
+func replaceAll(s, old, new string) string {
+ result := ""
+ for i := 0; i < len(s); i++ {
+ if i+len(old) <= len(s) && s[i:i+len(old)] == old {
+ result += new
+ i += len(old) - 1
+ } else {
+ result += string(s[i])
+ }
+ }
+ return result
+}