From f1e008670cd865520eb5f21fe6e7b56f02076a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 13:32:39 +0100 Subject: feat(config): supports multiple sections --- backend/config.go | 10 +- backend/home.go | 39 +++----- backend/logs.go | 201 -------------------------------------- backend/templates/components.html | 20 +--- backend/templates/home.html | 4 + backend/templates/log.html | 2 +- backend/templates/rss.xml | 12 +-- 7 files changed, 35 insertions(+), 253 deletions(-) delete mode 100644 backend/logs.go (limited to 'backend') diff --git a/backend/config.go b/backend/config.go index b59c00b..29e1397 100644 --- a/backend/config.go +++ b/backend/config.go @@ -30,7 +30,8 @@ type Config struct { DefaultImage string `toml:"default_image"` Quotes []string `toml:"quotes"` - LogFolder string `toml:"log_folder"` + Sections []Section `toml:"section"` + RootFolder string `toml:"root_folder"` PublicFolder string `toml:"public_folder"` @@ -56,7 +57,12 @@ func (c *Config) DefaultValues() { Header: "logo.jpg", Favicon: "favicon.jpg", } - c.LogFolder = "data/logs" + c.Sections = []Section{{ + Name: "logs", + Description: "Aut maxime voluptatibus ut dicta voluptates et ut alias. Sunt et incidunt similique et doloremque nostrum fugit autem. Ut omnis quo nisi. Accusantium voluptas fugit autem maiores numquam doloribus.", + Folder: "data/logs", + URI: "logs", + }} c.RootFolder = "data" c.PublicFolder = "public" c.Quotes = []string{"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do."} diff --git a/backend/home.go b/backend/home.go index b945313..2f0643f 100644 --- a/backend/home.go +++ b/backend/home.go @@ -2,25 +2,21 @@ package backend import ( "html/template" - "log/slog" "net/http" "os" "path/filepath" - "strconv" "github.com/go-chi/chi/v5" ) var ( - sortedLogs []*logData + //sortedSections = map[string][]*sectionData{} rootContent = map[string]*rootData{} ) type homeData struct { *data - Logs []*logData - PagesNumber int - CurrentPage int + Sections []*Section } func (h *homeData) SetData(d *data) { @@ -29,7 +25,7 @@ func (h *homeData) SetData(d *data) { func HandleHome(r *chi.Mux) { r.Get("/", func(w http.ResponseWriter, r *http.Request) { - d := handleGenericLogsDisplay(w, r, 3) + d := handleGenericSectionDisplay(w, r, 3) if d == nil { return } @@ -93,29 +89,16 @@ func handleGenericRoot(w http.ResponseWriter, r *http.Request, name string) { d.handleGeneric(w, r, "simple", d) } -func handleGenericLogsDisplay(w http.ResponseWriter, r *http.Request, maxLogsPerPage int) *homeData { - rawPage := r.URL.Query().Get("page") - page := 1 - if rawPage != "" { - var err error - page, err = strconv.Atoi(rawPage) - if err != nil || page < 1 { - slog.Warn("invalid page number", "rawPage", rawPage) - w.WriteHeader(http.StatusBadRequest) - return nil - } - } +func handleGenericSectionDisplay(_ http.ResponseWriter, r *http.Request, maxLogsPerPage int) *homeData { d := new(homeData) d.data = new(data) - if sortedLogs == nil { - sortLogs() - } - d.CurrentPage = page - d.PagesNumber = max(1, (len(sortedLogs)-1)/maxLogsPerPage+1) - if d.PagesNumber < page { - notFound(w, r) - return nil + cfg := r.Context().Value(configKey).(*Config) + for _, sec := range cfg.Sections { + if len(sec.Data) == 0 { + sec.sort() + } + sec.Data = sec.Data[:min(maxLogsPerPage, len(sec.Data))] + d.Sections = append(d.Sections, &sec) } - d.Logs = sortedLogs[(page-1)*maxLogsPerPage : min(page*maxLogsPerPage, len(sortedLogs))] return d } diff --git a/backend/logs.go b/backend/logs.go deleted file mode 100644 index 03d4f1f..0000000 --- a/backend/logs.go +++ /dev/null @@ -1,201 +0,0 @@ -package backend - -import ( - "fmt" - "html/template" - "log/slog" - "maps" - "net/http" - "os" - "path/filepath" - "slices" - "strings" - "sync" - "time" - - "github.com/go-chi/chi/v5" -) - -var ( - logs = map[string]*logData{} -) - -type logData struct { - *data - EntryInfo - LogTitle string - Content template.HTML - Slug string -} - -func (d *logData) SetData(dt *data) { - d.data = dt -} - -func (d *logData) PubDate() string { - return d.PubLocalDate.String() -} - -func (d *logData) PubDateRSS() string { - return d.PubLocalDate.AsTime(time.Local).Format(time.RFC1123Z) // because RFC822 in go isn't RFC822??? -} - -func (d *logData) Title() string { - return d.data.Title() -} - -type image struct { - Src string `toml:"src"` - Alt string `toml:"alt"` - Legend string `toml:"legend"` -} - -func LoadLogs(cfg *Config) bool { - dir, err := os.ReadDir(cfg.LogFolder) - if err != nil { - if !os.IsNotExist(err) { - slog.Error("reading log directory", "error", err) - return false - } - slog.Info("log directory does not exist, creating...") - err = os.MkdirAll(cfg.LogFolder, 0774) - if err != nil { - slog.Error("creating log directory", "error", err) - } - return false - } - slog.Info("checking log directory...", "path", cfg.LogFolder) - err = readLogDir(cfg.LogFolder, dir) - if err != nil { - slog.Error("reading log directory", "error", err, "path", cfg.LogFolder) - return false - } - slog.Info("all logs loaded") - return true -} - -func readLogDir(path string, dir []os.DirEntry) error { - var wg sync.WaitGroup - var mu sync.Mutex - for _, d := range dir { - p := filepath.Join(path, d.Name()) - if d.IsDir() { - dd, err := os.ReadDir(p) - if err != nil { - return err - } - if err = readLogDir(p, dd); err != nil { - return err - } - } else { - if !strings.HasSuffix(d.Name(), ".md") { - return fmt.Errorf("file %s is not a markdown file", d.Name()) - } - slug := strings.TrimSuffix(p, ".md") - _, ok := logs[slug] - if ok { - return fmt.Errorf("log already exists: %s", d.Name()) - } - dd := new(logData) - dd.data = new(data) - - wg.Add(1) - go func(p string, d os.DirEntry) { - defer wg.Done() - ok = parseLog(dd, &mu, slug, strings.TrimSuffix(d.Name(), ".md")) - if ok { - slog.Debug("log parsed", "path", p) - } else { - slog.Debug("log skipped", "path", p) - } - }(p, d) - } - } - wg.Wait() - sortLogs() - return nil -} - -func HandleLogs(r *chi.Mux) { - r.Get("/logs", handleLogList) - r.Route("/logs", func(r chi.Router) { - r.Get("/", handleLogList) - - r.Get("/rss", handleLogRSS) - r.Get("/rss/", handleLogRSS) - - r.Get("/{slug:[a-zA-Z0-9-]+}", handleLog) - r.Get("/{slug:[a-zA-Z0-9-]+}/", handleLog) - }) -} - -func handleLogList(w http.ResponseWriter, r *http.Request) { - d := handleGenericLogsDisplay(w, r, 5) - if d == nil { - return - } - d.title = "logs" - d.handleGeneric(w, r, "home_log", d) -} - -func handleLogRSS(w http.ResponseWriter, r *http.Request) { - d := handleGenericLogsDisplay(w, r, 5) - if d == nil { - return - } - d.title = "logs" - d.handleRSS(w, r, d) -} - -func handleLog(w http.ResponseWriter, r *http.Request) { - cfg := r.Context().Value(configKey).(*Config) - slug := chi.URLParam(r, "slug") - path := filepath.Join(cfg.LogFolder, slug) - d, ok := logs[path] - if !ok { - d = new(logData) - d.data = new(data) - if ok = parseLog(d, new(sync.Mutex), path, slug); !ok { - notFound(w, r) - return - } - } - d.handleGeneric(w, r, "log", d) -} - -func parseLog(d *logData, mu *sync.Mutex, path, slug string) bool { - d.Article = true - d.title = slug - d.Slug = slug - b, err := os.ReadFile(path + ".md") - if err != nil { - if os.IsNotExist(err) { - return false - } - panic(err) - } - var ok bool - d.Content, ok = parse(b, &d.EntryInfo, d.data) - if !ok { - return false - } - d.LogTitle = d.EntryInfo.Title - mu.Lock() - logs[path] = d - mu.Unlock() - return true -} - -func sortLogs() { - sortedLogs = slices.SortedFunc(maps.Values(logs), func(l *logData, l2 *logData) int { - lt := l.PubLocalDate.AsTime(time.UTC) - l2t := l2.PubLocalDate.AsTime(time.UTC) - // we want it reversed - if lt.Before(l2t) { - return 1 - } else if lt.After(l2t) { - return -1 - } - return 0 - }) -} diff --git a/backend/templates/components.html b/backend/templates/components.html index da133a6..9792784 100644 --- a/backend/templates/components.html +++ b/backend/templates/components.html @@ -1,26 +1,16 @@ {{define "logs_display"}}
- {{ range .Logs }} + {{ $uri := .URI }} + {{ range .Data }} - {{ end }} {{ if ne .PagesNumber 1 }} - {{ end }} + Voir plus
{{end}} diff --git a/backend/templates/home.html b/backend/templates/home.html index 7a76e48..ce4f4e8 100644 --- a/backend/templates/home.html +++ b/backend/templates/home.html @@ -4,6 +4,10 @@

logs

{{ .PageDescription }}

+ {{ range .Sections }} +
{{ template "logs_display" . }} +
+ {{ end }} {{end}} diff --git a/backend/templates/log.html b/backend/templates/log.html index 75e0a42..a384459 100644 --- a/backend/templates/log.html +++ b/backend/templates/log.html @@ -1,6 +1,6 @@ {{define "body"}}
-

{{ .LogTitle }}

+

{{ .DataTitle }}

{{ .Description }}

{{ .Img.Alt }} diff --git a/backend/templates/rss.xml b/backend/templates/rss.xml index c8390da..6d99272 100644 --- a/backend/templates/rss.xml +++ b/backend/templates/rss.xml @@ -3,18 +3,18 @@ {{ .Title }} - https://{{ .Domain }}/logs/ + https://{{ .Domain }}/{{ .URI }}/ {{ .PageDescription }} fr-fr {{ $domain := .Domain }} - {{ range .Logs }} + {{ range .Section.Data }} - {{ .LogTitle }} - https://{{ $domain }}/logs/{{ .Slug }} - https://{{ $domain }}/logs/{{ .Slug }} + {{ .DataTitle }} + https://{{ $domain }}/{{ .URI }}/{{ .Slug }} + https://{{ $domain }}/{{ .URI }}/{{ .Slug }} {{ .Description }} {{ .PubDateRSS }} {{ end }} - \ No newline at end of file + -- cgit v1.2.3 From ef3f8de38795a92dfc5d232a533c37d53794f1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 13:44:41 +0100 Subject: fix(section): cannot execute home_logs --- backend/templates/components.html | 9 +++++---- backend/templates/home.html | 6 ++++-- backend/templates/home_log.html | 9 ++++++++- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'backend') diff --git a/backend/templates/components.html b/backend/templates/components.html index 9792784..8f1bcc2 100644 --- a/backend/templates/components.html +++ b/backend/templates/components.html @@ -1,9 +1,8 @@ {{define "logs_display"}} {{end}} diff --git a/backend/templates/home.html b/backend/templates/home.html index ce4f4e8..3ff9ce3 100644 --- a/backend/templates/home.html +++ b/backend/templates/home.html @@ -1,12 +1,14 @@ {{define "body"}}
-

logs

+

{{ .Name }}

{{ .PageDescription }}

{{ range .Sections }}
- {{ template "logs_display" . }} +

{{ .Name }}

+

{{ .Description }}

+ {{ template "logs_display" . }}
{{ end }}
diff --git a/backend/templates/home_log.html b/backend/templates/home_log.html index 485661c..28bf36a 100644 --- a/backend/templates/home_log.html +++ b/backend/templates/home_log.html @@ -1,3 +1,10 @@ {{define "body"}} -
{{ template "logs_display" . }}
+
+ {{ range .Sections }} +
+

{{ .Name }}

+

{{ .Description }}

+
+ {{ template "logs_display" . }} {{ end }} +
{{end}} -- cgit v1.2.3 From 8d000018e132583bf4797ac9cb4ce2c4e96ed8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 14:40:26 +0100 Subject: feat(section): display paginate in full list --- backend/router.go | 2 +- backend/templates/components.html | 14 +++++++++++++- backend/templates/home.html | 2 +- backend/templates/home_log.html | 10 ---------- backend/templates/log.html | 11 ----------- 5 files changed, 15 insertions(+), 24 deletions(-) delete mode 100644 backend/templates/home_log.html delete mode 100644 backend/templates/log.html (limited to 'backend') diff --git a/backend/router.go b/backend/router.go index 59a02e3..fd72711 100644 --- a/backend/router.go +++ b/backend/router.go @@ -17,7 +17,7 @@ import ( ) const ( - Version = "0.3.0" + Version = "0.4.0" configKey = "config" isUpdateKey = "is_update" assetsFSKey = "assets_fs" diff --git a/backend/templates/components.html b/backend/templates/components.html index 8f1bcc2..72bf40e 100644 --- a/backend/templates/components.html +++ b/backend/templates/components.html @@ -1,4 +1,4 @@ -{{define "logs_display"}} +{{define "section_display"}}
{{ $uri := .URI }} {{ range .Data }}
@@ -11,7 +11,19 @@
{{ end }}
{{end}} diff --git a/backend/templates/home.html b/backend/templates/home.html index 3ff9ce3..d5dbb28 100644 --- a/backend/templates/home.html +++ b/backend/templates/home.html @@ -8,7 +8,7 @@

{{ .Name }}

{{ .Description }}

- {{ template "logs_display" . }} + {{ template "section_display" . }}
{{ end }} diff --git a/backend/templates/home_log.html b/backend/templates/home_log.html deleted file mode 100644 index 28bf36a..0000000 --- a/backend/templates/home_log.html +++ /dev/null @@ -1,10 +0,0 @@ -{{define "body"}} -
- {{ range .Sections }} -
-

{{ .Name }}

-

{{ .Description }}

-
- {{ template "logs_display" . }} {{ end }} -
-{{end}} diff --git a/backend/templates/log.html b/backend/templates/log.html deleted file mode 100644 index a384459..0000000 --- a/backend/templates/log.html +++ /dev/null @@ -1,11 +0,0 @@ -{{define "body"}} -
-

{{ .DataTitle }}

-

{{ .Description }}

-
- {{ .Img.Alt }} -
{{ .Img.Legend }}
-
- {{ .Content }} -
-{{end}} -- cgit v1.2.3 From 9c2d960a3b7728b7857ad71ed656be4a02d58599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 14:42:36 +0100 Subject: fix(backend): missing files --- backend/section.go | 275 ++++++++++++++++++++++++++++++++++++ backend/templates/data.html | 11 ++ backend/templates/home_section.html | 10 ++ 3 files changed, 296 insertions(+) create mode 100644 backend/section.go create mode 100644 backend/templates/data.html create mode 100644 backend/templates/home_section.html (limited to 'backend') diff --git a/backend/section.go b/backend/section.go new file mode 100644 index 0000000..931b7ca --- /dev/null +++ b/backend/section.go @@ -0,0 +1,275 @@ +package backend + +import ( + "fmt" + "html/template" + "iter" + "log/slog" + "maps" + "net/http" + "os" + "path/filepath" + "slices" + "strconv" + "strings" + "sync" + "time" + + "github.com/go-chi/chi/v5" +) + +var ( + sections = map[string]map[string]*sectionData{} +) + +type Section struct { + Name string `toml:"name"` + Folder string `toml:"folder"` + Description string `toml:"description"` + URI string `toml:"uri"` + Data []*sectionData `toml:"-"` + Paginate bool `toml:"-"` + PagesNumber int `toml:"-"` + CurrentPage int `toml:"-"` +} + +type sectionData struct { + *data + EntryInfo + DataTitle string + Content template.HTML + Slug string +} + +func (d *sectionData) SetData(dt *data) { + d.data = dt +} + +func (d *sectionData) PubDate() string { + return d.PubLocalDate.String() +} + +func (d *sectionData) PubDateRSS() string { + return d.PubLocalDate.AsTime(time.Local).Format(time.RFC1123Z) // because RFC822 in go isn't RFC822??? +} + +func (d *sectionData) Title() string { + return d.data.Title() +} + +type image struct { + Src string `toml:"src"` + Alt string `toml:"alt"` + Legend string `toml:"legend"` +} + +func (s *Section) Load(_ *Config) bool { + dir, err := os.ReadDir(s.Folder) + logger := slog.With("folder", s.Folder) + if err != nil { + if !os.IsNotExist(err) { + logger.Error("reading directory", "error", err) + return false + } + logger.Info("log directory does not exist, creating...") + err = os.MkdirAll(s.Folder, 0774) + if err != nil { + slog.Error("creating directory", "error", err) + } + return false + } + logger.Info("checking directory...", "path", s.Folder) + err = s.readDir(s.Folder, dir) + if err != nil { + slog.Error("reading directory", "error", err) + return false + } + logger.Info("all data loaded") + return true +} + +func (s *Section) readDir(path string, dir []os.DirEntry) error { + var wg sync.WaitGroup + var mu sync.Mutex + for _, d := range dir { + p := filepath.Join(path, d.Name()) + if d.IsDir() { + dd, err := os.ReadDir(p) + if err != nil { + return err + } + if err = s.readDir(p, dd); err != nil { + return err + } + } else { + if !strings.HasSuffix(d.Name(), ".md") { + return fmt.Errorf("file %s is not a markdown file", d.Name()) + } + slug := strings.TrimSuffix(p, ".md") + sec, ok := sections[s.Name] + if !ok { + sec = make(map[string]*sectionData, 2) + sections[s.Name] = sec + } + _, ok = sec[slug] + if ok { + return fmt.Errorf("data already exists: %s", d.Name()) + } + dd := new(sectionData) + dd.data = new(data) + + wg.Add(1) + go func(p string, d os.DirEntry) { + defer wg.Done() + ok = s.parse(dd, &mu, slug, strings.TrimSuffix(d.Name(), ".md")) + if ok { + slog.Debug("data parsed", "path", p) + } else { + slog.Debug("data skipped", "path", p) + } + }(p, d) + } + } + wg.Wait() + s.sort() + return nil +} + +func (s *Section) Handle(r *chi.Mux) { + base := "/" + s.URI + r.Get(base, s.handleList) + r.Route(base, func(r chi.Router) { + r.Get("/", s.handleList) + + r.Get("/rss", s.handleRSS) + r.Get("/rss/", s.handleRSS) + + r.Get("/{slug:[a-zA-Z0-9-]+}", s.handleOne) + r.Get("/{slug:[a-zA-Z0-9-]+}/", s.handleOne) + }) +} + +func (s *Section) handleList(w http.ResponseWriter, r *http.Request) { + p := s.handlePagination(w, r, 5) + if p == nil { + return + } + d := new(homeData) + d.data = new(data) + d.title = s.Name + sec := *s + sec.Data = sec.Data[p.Start:p.End] + sec.Paginate = true + sec.CurrentPage = p.Current + sec.PagesNumber = p.Max + d.Sections = append(d.Sections, &sec) + d.handleGeneric(w, r, "home_section", d) +} + +func (s *Section) handleRSS(w http.ResponseWriter, r *http.Request) { + d := handleGenericSectionDisplay(w, r, 5) + if d == nil { + return + } + d.title = s.Name + d.handleRSS(w, r, d) +} + +func (s *Section) handleOne(w http.ResponseWriter, r *http.Request) { + slug := chi.URLParam(r, "slug") + path := filepath.Join(s.Folder, slug) + sec, ok := sections[s.Name] + var d *sectionData + if ok { + d, ok = sec[path] + } + if !ok { + d = new(sectionData) + d.data = new(data) + if ok = s.parse(d, new(sync.Mutex), path, slug); !ok { + notFound(w, r) + return + } + } + d.handleGeneric(w, r, "data", d) +} + +func (s *Section) parse(d *sectionData, mu *sync.Mutex, path, slug string) bool { + d.Article = true + d.DataTitle = slug + d.Slug = slug + b, err := os.ReadFile(path + ".md") + if err != nil { + if os.IsNotExist(err) { + return false + } + panic(err) + } + var ok bool + d.Content, ok = parse(b, &d.EntryInfo, d.data) + if !ok { + return false + } + d.DataTitle = d.EntryInfo.Title + mu.Lock() + sec, ok := sections[s.Name] + if !ok { + sec = make(map[string]*sectionData, 2) + sections[s.Name] = sec + } + sec[path] = d + mu.Unlock() + return true +} + +func (s *Section) sort() { + s.Data = sort(maps.Values(sections[s.Name])) +} + +func sort(values iter.Seq[*sectionData]) []*sectionData { + return slices.SortedFunc(values, func(l *sectionData, l2 *sectionData) int { + lt := l.PubLocalDate.AsTime(time.UTC) + l2t := l2.PubLocalDate.AsTime(time.UTC) + // we want it reversed + if lt.Before(l2t) { + return 1 + } else if lt.After(l2t) { + return -1 + } + return 0 + }) +} + +type pagination struct { + Current int + Max int + Start int + End int +} + +func (s *Section) handlePagination(w http.ResponseWriter, r *http.Request, maxLogsPerPage int) *pagination { + rawPage := r.URL.Query().Get("page") + page := 1 + if rawPage != "" { + var err error + page, err = strconv.Atoi(rawPage) + if err != nil || page < 1 { + slog.Warn("invalid page number", "rawPage", rawPage) + w.WriteHeader(http.StatusBadRequest) + return nil + } + } + if len(s.Data) == 0 { + s.sort() + } + p := new(pagination) + p.Current = page + p.Max = max(1, (len(s.Data)-1)/maxLogsPerPage+1) + if p.Max < page { + notFound(w, r) + return nil + } + p.Start = (page - 1) * maxLogsPerPage + p.End = min(page*maxLogsPerPage, len(s.Data)) + return p +} diff --git a/backend/templates/data.html b/backend/templates/data.html new file mode 100644 index 0000000..a384459 --- /dev/null +++ b/backend/templates/data.html @@ -0,0 +1,11 @@ +{{define "body"}} +
+

{{ .DataTitle }}

+

{{ .Description }}

+
+ {{ .Img.Alt }} +
{{ .Img.Legend }}
+
+ {{ .Content }} +
+{{end}} diff --git a/backend/templates/home_section.html b/backend/templates/home_section.html new file mode 100644 index 0000000..cf7595d --- /dev/null +++ b/backend/templates/home_section.html @@ -0,0 +1,10 @@ +{{define "body"}} +
+ {{ range .Sections }} +
+

{{ .Name }}

+

{{ .Description }}

+
+ {{ template "section_display" . }} {{ end }} +
+{{end}} -- cgit v1.2.3 From 1f0cf029644861bc31a363ecfdbfcb6ebafff3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 15:53:45 +0100 Subject: fix(section): bad description in og --- backend/section.go | 1 + backend/templates/components.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'backend') diff --git a/backend/section.go b/backend/section.go index 931b7ca..01ffc90 100644 --- a/backend/section.go +++ b/backend/section.go @@ -163,6 +163,7 @@ func (s *Section) handleList(w http.ResponseWriter, r *http.Request) { sec.CurrentPage = p.Current sec.PagesNumber = p.Max d.Sections = append(d.Sections, &sec) + d.PageDescription = sec.Description d.handleGeneric(w, r, "home_section", d) } diff --git a/backend/templates/components.html b/backend/templates/components.html index 72bf40e..5365445 100644 --- a/backend/templates/components.html +++ b/backend/templates/components.html @@ -2,7 +2,7 @@
{{ $uri := .URI }} {{ range .Data }}
-

{{ .DataTitle }}

+

{{ .DataTitle }}

{{ .Img.Alt }}
{{ .Img.Legend }}
-- cgit v1.2.3 From 0c3a89ee546a2a3215eb32d9786dabeda051812d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 16:04:14 +0100 Subject: fix(section): bad template for RSS --- backend/data.go | 10 +++++++++- backend/section.go | 1 + backend/templates/rss.xml | 10 ++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'backend') diff --git a/backend/data.go b/backend/data.go index 6ca6020..794b763 100644 --- a/backend/data.go +++ b/backend/data.go @@ -92,6 +92,7 @@ func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string }, "next": func(i int) int { return i + 1 }, "before": func(i int) int { return i - 1 }, + "first": templateFirst, }).ParseFS(templates, "templates/components.html", fmt.Sprintf("templates/%s.html", name), "templates/base.html") if err != nil { panic(err) @@ -116,7 +117,7 @@ func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string func (d *data) handleRSS(w http.ResponseWriter, r *http.Request, custom dataUsable) { cfg := r.Context().Value(configKey).(*Config) d.merge(cfg, r) - t, err := txt.ParseFS(templates, "templates/rss.xml") + t, err := txt.New("").Funcs(txt.FuncMap{"first": templateFirst}).ParseFS(templates, "templates/rss.xml") if err != nil { panic(err) } @@ -197,3 +198,10 @@ func getAsset(ctx context.Context, path string) *assetData { assets[path] = asset return asset } + +func templateFirst(a []*Section) *Section { + if len(a) == 0 { + return nil + } + return a[0] +} diff --git a/backend/section.go b/backend/section.go index 01ffc90..06b48cc 100644 --- a/backend/section.go +++ b/backend/section.go @@ -173,6 +173,7 @@ func (s *Section) handleRSS(w http.ResponseWriter, r *http.Request) { return } d.title = s.Name + d.PageDescription = s.Description d.handleRSS(w, r, d) } diff --git a/backend/templates/rss.xml b/backend/templates/rss.xml index 6d99272..2abca8e 100644 --- a/backend/templates/rss.xml +++ b/backend/templates/rss.xml @@ -3,15 +3,17 @@ {{ .Title }} - https://{{ .Domain }}/{{ .URI }}/ + {{ $sec := first .Sections }} + {{ $uri := $sec.URI }} + https://{{ .Domain }}/{{ $uri }}/ {{ .PageDescription }} fr-fr {{ $domain := .Domain }} - {{ range .Section.Data }} + {{ range $sec.Data }} {{ .DataTitle }} - https://{{ $domain }}/{{ .URI }}/{{ .Slug }} - https://{{ $domain }}/{{ .URI }}/{{ .Slug }} + https://{{ $domain }}/{{ $uri }}/{{ .Slug }} + https://{{ $domain }}/{{ $uri }}/{{ .Slug }} {{ .Description }} {{ .PubDateRSS }} -- cgit v1.2.3 From 3ce41d99d688410a361d83767b50b64a35b569d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 17:21:41 +0100 Subject: feat(sections): general rss feed --- backend/config.go | 1 + backend/data.go | 14 +++++++++++++- backend/home.go | 40 +++++++++++++++++++++++++++++++++++----- backend/section.go | 4 ++-- backend/templates/base.html | 2 +- backend/templates/rss.xml | 10 +++++----- 6 files changed, 57 insertions(+), 14 deletions(-) (limited to 'backend') diff --git a/backend/config.go b/backend/config.go index 29e1397..cd24592 100644 --- a/backend/config.go +++ b/backend/config.go @@ -29,6 +29,7 @@ type Config struct { Description string `toml:"description"` DefaultImage string `toml:"default_image"` Quotes []string `toml:"quotes"` + Language string `toml:"language"` Sections []Section `toml:"section"` diff --git a/backend/data.go b/backend/data.go index 794b763..809e6e6 100644 --- a/backend/data.go +++ b/backend/data.go @@ -36,6 +36,7 @@ type data struct { Links []Link Logo *Logo Quote string + Language string } func (d *data) SetData(data *data) { @@ -74,6 +75,9 @@ func (d *data) merge(cfg *Config, r *http.Request) { } d.URL = r.URL.Path } + if d.Language == "" { + d.Language = cfg.Language + } } func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string, custom dataUsable) { @@ -117,7 +121,15 @@ func (d *data) handleGeneric(w http.ResponseWriter, r *http.Request, name string func (d *data) handleRSS(w http.ResponseWriter, r *http.Request, custom dataUsable) { cfg := r.Context().Value(configKey).(*Config) d.merge(cfg, r) - t, err := txt.New("").Funcs(txt.FuncMap{"first": templateFirst}).ParseFS(templates, "templates/rss.xml") + t, err := txt.New("").Funcs(txt.FuncMap{ + "first": templateFirst, + "uri": func(s string) string { + if s == "" { + return "" + } + return s + "/" + }, + }).ParseFS(templates, "templates/rss.xml") if err != nil { panic(err) } diff --git a/backend/home.go b/backend/home.go index 2f0643f..8f274e8 100644 --- a/backend/home.go +++ b/backend/home.go @@ -2,15 +2,16 @@ package backend import ( "html/template" + "iter" "net/http" "os" "path/filepath" + "slices" "github.com/go-chi/chi/v5" ) var ( - //sortedSections = map[string][]*sectionData{} rootContent = map[string]*rootData{} ) @@ -25,7 +26,8 @@ func (h *homeData) SetData(d *data) { func HandleHome(r *chi.Mux) { r.Get("/", func(w http.ResponseWriter, r *http.Request) { - d := handleGenericSectionDisplay(w, r, 3) + cfg := r.Context().Value(configKey).(*Config) + d := handleGenericSectionDisplay(w, r, cfg.Sections, 3) if d == nil { return } @@ -58,6 +60,8 @@ func HandleRoot(r *chi.Mux, cfg *Config) { if err != nil && !os.IsExist(err) { panic(err) } + r.Get("/rss", handleGenericRSS) + r.Get("/rss/", handleGenericRSS) r.Get("/{name:[a-zA-Z-]+}", func(w http.ResponseWriter, r *http.Request) { handleGenericRoot(w, r, chi.URLParam(r, "name")) }) @@ -89,11 +93,37 @@ func handleGenericRoot(w http.ResponseWriter, r *http.Request, name string) { d.handleGeneric(w, r, "simple", d) } -func handleGenericSectionDisplay(_ http.ResponseWriter, r *http.Request, maxLogsPerPage int) *homeData { - d := new(homeData) - d.data = new(data) +func handleGenericRSS(w http.ResponseWriter, r *http.Request) { cfg := r.Context().Value(configKey).(*Config) + var data iter.Seq[*sectionData] for _, sec := range cfg.Sections { + if len(sec.Data) == 0 { + sec.sort() + } + var sl []*sectionData + for _, d := range sec.Data[:min(3, len(sec.Data))] { + dd := *d + dd.Slug = sec.URI + "/" + dd.Slug + sl = append(sl, &dd) + } + if data == nil { + data = slices.Values(sl) + } else { + data = slices.Values(slices.AppendSeq(sl, data)) + } + } + var s Section + s.Data = sort(data) + s.Name = cfg.Name + s.Description = cfg.Description + s.URI = "" + s.handleRSS(w, r) +} + +func handleGenericSectionDisplay(_ http.ResponseWriter, _ *http.Request, sections []Section, maxLogsPerPage int) *homeData { + d := new(homeData) + d.data = new(data) + for _, sec := range sections { if len(sec.Data) == 0 { sec.sort() } diff --git a/backend/section.go b/backend/section.go index 06b48cc..a22d286 100644 --- a/backend/section.go +++ b/backend/section.go @@ -78,7 +78,7 @@ func (s *Section) Load(_ *Config) bool { } return false } - logger.Info("checking directory...", "path", s.Folder) + logger.Info("checking directory...") err = s.readDir(s.Folder, dir) if err != nil { slog.Error("reading directory", "error", err) @@ -168,7 +168,7 @@ func (s *Section) handleList(w http.ResponseWriter, r *http.Request) { } func (s *Section) handleRSS(w http.ResponseWriter, r *http.Request) { - d := handleGenericSectionDisplay(w, r, 5) + d := handleGenericSectionDisplay(w, r, []Section{*s}, 5) if d == nil { return } diff --git a/backend/templates/base.html b/backend/templates/base.html index 0a54096..436a1c2 100644 --- a/backend/templates/base.html +++ b/backend/templates/base.html @@ -1,5 +1,5 @@ - + diff --git a/backend/templates/rss.xml b/backend/templates/rss.xml index 2abca8e..039a2f7 100644 --- a/backend/templates/rss.xml +++ b/backend/templates/rss.xml @@ -4,16 +4,16 @@ {{ .Title }} {{ $sec := first .Sections }} - {{ $uri := $sec.URI }} - https://{{ .Domain }}/{{ $uri }}/ + {{ $uri := uri $sec.URI }} + https://{{ .Domain }}/{{ $uri }} {{ .PageDescription }} - fr-fr + {{ .Language }} {{ $domain := .Domain }} {{ range $sec.Data }} {{ .DataTitle }} - https://{{ $domain }}/{{ $uri }}/{{ .Slug }} - https://{{ $domain }}/{{ $uri }}/{{ .Slug }} + https://{{ $domain }}/{{ $uri }}{{ .Slug }} + https://{{ $domain }}/{{ $uri }}{{ .Slug }} {{ .Description }} {{ .PubDateRSS }} -- cgit v1.2.3 From 1e2ad3a8f8cd2c12786b92210616325a33d1b209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Mon, 27 Oct 2025 17:32:41 +0100 Subject: feat(home): better display of sections --- backend/templates/home.html | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'backend') diff --git a/backend/templates/home.html b/backend/templates/home.html index d5dbb28..d574525 100644 --- a/backend/templates/home.html +++ b/backend/templates/home.html @@ -4,12 +4,14 @@

{{ .Name }}

{{ .PageDescription }}

- {{ range .Sections }} -
-

{{ .Name }}

-

{{ .Description }}

- {{ template "section_display" . }} +
+ {{ range .Sections }} +
+

{{ .Name }}

+

{{ .Description }}

+ {{ template "section_display" . }} +
+ {{ end }}
- {{ end }} {{end}} -- cgit v1.2.3