Skip to content

Commit ebb9085

Browse files
committed
Add RSS feed generation and configure BaseURL
1 parent 454b39c commit ebb9085

File tree

2 files changed

+105
-9
lines changed

2 files changed

+105
-9
lines changed

cmd/plan/main.go

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"encoding/xml"
45
"flag"
56
"fmt"
67
"log"
@@ -25,6 +26,28 @@ type PlanContext struct {
2526
Template string // Custom template content
2627
}
2728

29+
type Rss struct {
30+
XMLName xml.Name `xml:"rss"`
31+
Version string `xml:"version,attr"`
32+
Channel Channel `xml:"channel"`
33+
}
34+
35+
type Channel struct {
36+
Title string `xml:"title"`
37+
Link string `xml:"link"`
38+
Description string `xml:"description"`
39+
Items []Item `xml:"item"`
40+
}
41+
42+
type Item struct {
43+
Title string `xml:"title"`
44+
Link string `xml:"link"`
45+
Description string `xml:"description"`
46+
Content string `xml:"content:encoded"`
47+
PubDate string `xml:"pubDate"`
48+
Guid string `xml:"guid"`
49+
}
50+
2851
func main() {
2952
// Define flags
3053
var inputPath string
@@ -185,22 +208,70 @@ func build(ctx *PlanContext) {
185208
log.Fatalf("Failed to build current page: %v", err)
186209
}
187210

188-
if err := buildHistory(ctx); err != nil {
211+
// Prepare RSS items
212+
var rssItems []Item
213+
214+
// Add current post
215+
r := render.New(&ctx.Config, ctx.Template)
216+
bodyBytes, err := r.RenderBody(content)
217+
if err == nil {
218+
link := ctx.Config.BaseURL + "/"
219+
item := Item{
220+
Title: ctx.Config.Title,
221+
Link: link,
222+
Description: string(bodyBytes),
223+
Content: string(bodyBytes),
224+
PubDate: info.ModTime().Format(time.RFC1123Z),
225+
Guid: link,
226+
}
227+
rssItems = append(rssItems, item)
228+
} else {
229+
log.Printf("Warning: Failed to render current content for RSS: %v", err)
230+
}
231+
232+
historyItems, err := buildHistory(ctx)
233+
if err != nil {
189234
log.Printf("Warning: Failed to build history (is this a git repo?): %v", err)
190235
}
236+
rssItems = append(rssItems, historyItems...)
237+
238+
// Generate RSS Feed
239+
rss := Rss{
240+
Version: "2.0",
241+
Channel: Channel{
242+
Title: ctx.Config.Title,
243+
Link: ctx.Config.BaseURL,
244+
Description: fmt.Sprintf("Updates for %s", ctx.Config.Title),
245+
Items: rssItems,
246+
},
247+
}
248+
249+
rssFile := filepath.Join(ctx.OutputDir, "rss.xml")
250+
f, err := os.Create(rssFile)
251+
if err != nil {
252+
log.Fatalf("Failed to create RSS file: %v", err)
253+
}
254+
defer f.Close()
255+
256+
f.WriteString(xml.Header)
257+
enc := xml.NewEncoder(f)
258+
enc.Indent("", " ")
259+
if err := enc.Encode(rss); err != nil {
260+
log.Fatalf("Failed to encode RSS: %v", err)
261+
}
191262

192263
fmt.Println("Build complete.")
193264
}
194265

195266
// buildHistory reconstructs the past versions of the plan file using git history.
196267
// It iterates through unique dates in the git log, retrieves the file content for that date,
197268
// and generates static pages for each day, as well as year and month index pages.
198-
func buildHistory(ctx *PlanContext) error {
269+
func buildHistory(ctx *PlanContext) ([]Item, error) {
199270
fmt.Println("Building history...")
200271

201272
history, err := getGitHistory(ctx.PlanDir, ctx.PlanFile)
202273
if err != nil {
203-
return err
274+
return nil, err
204275
}
205276

206277
var dates []string
@@ -215,6 +286,10 @@ func buildHistory(ctx *PlanContext) error {
215286
Path string
216287
}
217288
tree := make(map[string]map[string][]dayEntry)
289+
var rssItems []Item
290+
291+
// Reuse renderer if config doesn't change per file
292+
r := render.New(&ctx.Config, ctx.Template)
218293

219294
for _, dateStr := range dates {
220295
hash := history[dateStr]
@@ -236,15 +311,34 @@ func buildHistory(ctx *PlanContext) error {
236311
outPath := filepath.Join(outDir, "index.html")
237312

238313
if err := renderAndWrite(ctx, content, t, outPath); err != nil {
239-
return err
314+
return nil, err
315+
}
316+
317+
// Add to RSS
318+
relPath := fmt.Sprintf("/%s/%s/%s", year, month, day)
319+
link := ctx.Config.BaseURL + relPath
320+
321+
// We need the body content. renderAndWrite does it but doesn't return it.
322+
// We'll just re-render body here.
323+
bodyBytes, err := r.RenderBody(content)
324+
if err == nil {
325+
item := Item{
326+
Title: dateStr,
327+
Link: link,
328+
Description: string(bodyBytes),
329+
Content: string(bodyBytes),
330+
PubDate: t.Format(time.RFC1123Z),
331+
Guid: link,
332+
}
333+
rssItems = append(rssItems, item)
240334
}
241335

242336
if tree[year] == nil {
243337
tree[year] = make(map[string][]dayEntry)
244338
}
245339
tree[year][month] = append(tree[year][month], dayEntry{
246340
DateStr: dateStr,
247-
Path: fmt.Sprintf("/%s/%s/%s", year, month, day),
341+
Path: relPath,
248342
})
249343
}
250344

@@ -263,7 +357,7 @@ func buildHistory(ctx *PlanContext) error {
263357
yearContent += fmt.Sprintf("- [%s](%s)\n", link.DateStr, link.Path)
264358
}
265359
if err := renderAndWrite(ctx, []byte(yearContent), time.Now(), filepath.Join(ctx.OutputDir, year, "index.html")); err != nil {
266-
return err
360+
return nil, err
267361
}
268362

269363
for month, days := range months {
@@ -279,11 +373,11 @@ func buildHistory(ctx *PlanContext) error {
279373
monthContent += fmt.Sprintf("- [%s](%s)\n", link.DateStr, link.Path)
280374
}
281375
if err := renderAndWrite(ctx, []byte(monthContent), time.Now(), filepath.Join(ctx.OutputDir, year, month, "index.html")); err != nil {
282-
return err
376+
return nil, err
283377
}
284378
}
285379
}
286-
return nil
380+
return rssItems, nil
287381
}
288382

289383
func renderAndWrite(ctx *PlanContext, content []byte, modTime time.Time, outPath string) error {
@@ -431,7 +525,7 @@ func edit(ctx *PlanContext) {
431525
fullCmd := fmt.Sprintf("%s %q", editor, file)
432526
cmd = exec.Command("sh", "-c", fullCmd)
433527
}
434-
528+
435529
cmd.Stdin = os.Stdin
436530
cmd.Stdout = os.Stdout
437531
cmd.Stderr = os.Stderr

internal/config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type Config struct {
1313
Shell string `json:"shell"`
1414
Timezone string `json:"timezone"`
1515
Title string `json:"title"`
16+
BaseURL string `json:"base_url"`
1617
}
1718

1819
// DefaultConfig returns the default configuration based on environment variables
@@ -31,6 +32,7 @@ func DefaultConfig() Config {
3132
Shell: shell,
3233
Timezone: "America/Los_Angeles", // Default fallback
3334
Title: "Plan",
35+
BaseURL: "http://localhost:8081", // Default base URL for local preview
3436
}
3537
}
3638

0 commit comments

Comments
 (0)