88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
// Package changelog serves the "Обновления" settings tab — a
|
|
// human-maintained CHANGELOG.md (repo-root-of-backend, Keep-a-Changelog-
|
|
// lite format: `## YYYY-MM-DD` release headers, `### Добавлено/Изменено/
|
|
// Исправлено` category subsections) parsed into JSON on every request.
|
|
// Deliberately file-based rather than a DB table: entries are meant to be
|
|
// written once, by whoever runs deploy.sh for a release, not edited by
|
|
// staff through the UI — a file staff can `git log` / review in a PR is a
|
|
// better source of truth for "what actually shipped" than a table anyone
|
|
// with settings access could silently rewrite.
|
|
package changelog
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
const changelogPath = "CHANGELOG.md"
|
|
|
|
type Entry struct {
|
|
Date string `json:"date"`
|
|
Categories []EntryCategory `json:"categories"`
|
|
}
|
|
|
|
type EntryCategory struct {
|
|
Name string `json:"name"`
|
|
Items []string `json:"items"`
|
|
}
|
|
|
|
type Handler struct{}
|
|
|
|
func NewHandler() *Handler {
|
|
return &Handler{}
|
|
}
|
|
|
|
// parse reads the Keep-a-Changelog-lite format described in the package
|
|
// doc comment. Deliberately lenient: any line that doesn't match a known
|
|
// header shape is treated as a bullet under whatever category/entry is
|
|
// currently open, rather than erroring the whole page out over one typo'd
|
|
// line in a hand-edited markdown file.
|
|
func parse(r *bufio.Scanner) []Entry {
|
|
var entries []Entry
|
|
var cur *Entry
|
|
var curCat *EntryCategory
|
|
|
|
for r.Scan() {
|
|
line := strings.TrimSpace(r.Text())
|
|
switch {
|
|
case strings.HasPrefix(line, "## "):
|
|
entries = append(entries, Entry{Date: strings.TrimSpace(strings.TrimPrefix(line, "## "))})
|
|
cur = &entries[len(entries)-1]
|
|
curCat = nil
|
|
case strings.HasPrefix(line, "### "):
|
|
if cur == nil {
|
|
continue
|
|
}
|
|
cur.Categories = append(cur.Categories, EntryCategory{Name: strings.TrimSpace(strings.TrimPrefix(line, "### "))})
|
|
curCat = &cur.Categories[len(cur.Categories)-1]
|
|
case strings.HasPrefix(line, "- "):
|
|
if curCat == nil {
|
|
continue
|
|
}
|
|
curCat.Items = append(curCat.Items, strings.TrimSpace(strings.TrimPrefix(line, "- ")))
|
|
}
|
|
}
|
|
return entries
|
|
}
|
|
|
|
// List is staffAuth-only, no permission gate — "what's new" is useful
|
|
// information for every role, same reasoning InterfaceTab.jsx's own
|
|
// no-permission-gate comment gives for personal display prefs.
|
|
func (h *Handler) List(c *fiber.Ctx) error {
|
|
f, err := os.Open(changelogPath)
|
|
if err != nil {
|
|
// Missing file isn't a server error — just nothing to show yet.
|
|
return c.JSON(fiber.Map{"entries": []Entry{}})
|
|
}
|
|
defer f.Close()
|
|
|
|
entries := parse(bufio.NewScanner(f))
|
|
if entries == nil {
|
|
entries = []Entry{}
|
|
}
|
|
return c.JSON(fiber.Map{"entries": entries})
|
|
}
|