diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2025-10-02 21:30:34 +0200 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2025-10-02 21:30:34 +0200 |
| commit | 5dfd71bfe1c0e25da413f00256a302b13c88d26d (patch) | |
| tree | ccf3adc4ac0a6caea36ff58f50fa929862a5bc08 | |
| parent | 1e915322be3c370a682687614442c7853287b962 (diff) | |
perf(backend): generate content during load
| -rw-r--r-- | backend/data.go | 4 | ||||
| -rw-r--r-- | backend/logs.go | 66 | ||||
| -rw-r--r-- | backend/router.go | 20 | ||||
| -rw-r--r-- | backend/templates/base.html | 11 | ||||
| -rw-r--r-- | main.go | 2 |
5 files changed, 67 insertions, 36 deletions
diff --git a/backend/data.go b/backend/data.go index cd1ea9e..f3e8b42 100644 --- a/backend/data.go +++ b/backend/data.go @@ -89,3 +89,7 @@ func (d *data) Title() string { } return title } + +func (d *data) PubDate() string { + return "" +} diff --git a/backend/logs.go b/backend/logs.go index e25c638..d15be41 100644 --- a/backend/logs.go +++ b/backend/logs.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "strings" + "sync" "git.anhgelus.world/anhgelus/small-world/markdown" "github.com/go-chi/chi/v5" @@ -16,22 +17,26 @@ import ( ) var ( - logs = map[string]string{} - loadedLogs = map[string]*logData{} + logs = map[string]*logData{} ) type logData struct { *data - LogTitle string `toml:"title"` - Description string `toml:"description"` - Img image `toml:"image"` - Content template.HTML `toml:"-"` + LogTitle string `toml:"title"` + Description string `toml:"description"` + Img image `toml:"image"` + pubDate toml.LocalDate `toml:"publication_date"` + Content template.HTML `toml:"-"` } func (d *logData) SetData(dt *data) { d.data = dt } +func (d *logData) PubDate() string { + return d.pubDate.String() +} + type image struct { Src string `toml:"src"` Alt string `toml:"alt"` @@ -62,6 +67,7 @@ func LoadLogs(cfg *Config) bool { } func readLogDir(path string, dir []os.DirEntry) error { + var wg sync.WaitGroup for _, d := range dir { p := filepath.Join(path, d.Name()) if d.IsDir() { @@ -76,18 +82,31 @@ func readLogDir(path string, dir []os.DirEntry) error { if !strings.HasSuffix(d.Name(), ".md") { return fmt.Errorf("file %s is not a markdown file", d.Name()) } - _, ok := logs[d.Name()] + slug := strings.TrimSuffix(p, ".md") + _, ok := logs[slug] if ok { return fmt.Errorf("log already exists: %s", d.Name()) } - logs[strings.TrimSuffix(d.Name(), ".md")] = p + dd := new(logData) + dd.data = new(data) + go func() { + wg.Add(1) + defer wg.Done() + ok = parseLog(dd, slug, strings.TrimSuffix(d.Name(), ".md")) + if ok { + slog.Debug("log parsed", "path", p) + } else { + slog.Debug("log skipped", "path", p) + } + }() } } + wg.Wait() return nil } func HandleLogs(r *chi.Mux) { - r.Route("/logs", func(r chi.Router) { + r.Route("/log", func(r chi.Router) { r.Get("/", handleLogList) r.Get("/{slug:[a-zA-Z0-9-]+}", handleLog) }) @@ -98,32 +117,30 @@ func handleLogList(w http.ResponseWriter, r *http.Request) { } func handleLog(w http.ResponseWriter, r *http.Request) { + cfg := r.Context().Value("config").(*Config) slug := chi.URLParam(r, "slug") - path, ok := logs[slug] - if !ok { - http.NotFoundHandler().ServeHTTP(w, r) - return - } - var d *logData - d, ok = loadedLogs[slug] + path := filepath.Join(cfg.LogFolder, slug) + d, ok := logs[path] if !ok { d = new(logData) d.data = new(data) - d.Article = true - d.LogTitle = slug - d.title = slug - if ok = parseLog(d, path); !ok { - w.WriteHeader(http.StatusInternalServerError) + if ok = parseLog(d, path, slug); !ok { + http.NotFoundHandler().ServeHTTP(w, r) return } - loadedLogs[slug] = d } d.handleGeneric(w, r, "log", d) } -func parseLog(d *logData, path string) bool { - b, err := os.ReadFile(path) +func parseLog(d *logData, path, slug string) bool { + d.Article = true + d.LogTitle = slug + d.title = slug + b, err := os.ReadFile(path + ".md") if err != nil { + if os.IsNotExist(err) { + return false + } panic(err) } var dd string @@ -147,5 +164,6 @@ func parseLog(d *logData, path string) bool { fmt.Println(errMd.Pretty()) return false } + logs[path] = d return true } diff --git a/backend/router.go b/backend/router.go index 374e28b..33c685d 100644 --- a/backend/router.go +++ b/backend/router.go @@ -20,28 +20,38 @@ const Version = "0.1.0" //go:embed templates var templates embed.FS -func NewRouter(debug bool, cfg *Config) *chi.Mux { +func SetupLogger(debug bool) { logFormat := httplog.SchemaECS.Concise(!debug) + logLevel := slog.LevelWarn + if debug { + logLevel = slog.LevelDebug + } + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ ReplaceAttr: logFormat.ReplaceAttr, + Level: logLevel, })).With( slog.String("app", "anhgelus/small-web"), slog.String("version", Version), ) + slog.SetDefault(logger) +} + +func NewRouter(debug bool, cfg *Config) *chi.Mux { + r := chi.NewRouter() + logLevel := slog.LevelWarn if debug { logLevel = slog.LevelDebug } - r := chi.NewRouter() - r.Use(middleware.Timeout(30 * time.Second)) - r.Use(httplog.RequestLogger(logger, &httplog.Options{ + r.Use(httplog.RequestLogger(slog.Default(), &httplog.Options{ Level: logLevel, // Set log output to Elastic Common Schema (ECS) format. - Schema: logFormat, + Schema: httplog.SchemaECS.Concise(!debug), RecoverPanics: true, Skip: func(req *http.Request, respStatus int) bool { return respStatus == http.StatusNotFound || respStatus == http.StatusMethodNotAllowed diff --git a/backend/templates/base.html b/backend/templates/base.html index 34a7c7f..bef493f 100644 --- a/backend/templates/base.html +++ b/backend/templates/base.html @@ -1,5 +1,5 @@ <!doctype html> -<html lang="fr"> +<html lang="fr" prefix="og: https://ogp.me/ns/article#"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> @@ -15,6 +15,7 @@ <meta property="og:description" content="{{ .Description }}" /> <meta property="og:local" content="fr_FR" /> <meta property="og:site_name" content="{{ .Name }}" /> + {{ if ne .PubDate "" }}<meta property="article:published_time" content="{{ .PubDate }}">{{ end }} <!-- Twitter --> <meta name="twitter:card" content="summary_large_image" /> <meta property="twitter:domain" content="{{ .Domain }}" /> @@ -31,13 +32,9 @@ </nav> </header> {{ if .Article }} -<main> - {{ template "body" . }} -</main> +<main>{{ template "body" . }}</main> {{ else }} -<article> - {{ template "body" . }} -</article> +<article>{{ template "body" . }}</article> {{ end }} <footer> <p>© 2025 - Anhgelus Morthuuzh</p> @@ -56,6 +56,8 @@ func init() { func main() { flag.Parse() + backend.SetupLogger(dev) + cfg, ok := backend.LoadConfig(configFile) if !ok { slog.Info("exiting") |
