155 lines
3.7 KiB
Go
155 lines
3.7 KiB
Go
package handlers
|
|
|
|
// blog implementation concept
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"git.tijl.dev/tijl/tijl.dev-core/internal/i18n"
|
|
log "git.tijl.dev/tijl/tijl.dev-core/modules/logger"
|
|
"git.tijl.dev/tijl/tijl.dev-core/modules/web"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/yuin/goldmark"
|
|
"github.com/yuin/goldmark-meta"
|
|
"github.com/yuin/goldmark/extension"
|
|
"github.com/yuin/goldmark/parser"
|
|
)
|
|
|
|
type Post struct {
|
|
Meta PostMeta
|
|
Content template.HTML
|
|
}
|
|
|
|
type PostMeta struct {
|
|
Title string
|
|
Slug string
|
|
Description string
|
|
Author string
|
|
Language string
|
|
PublishDate time.Time
|
|
UpdatedDate time.Time
|
|
Tags []string
|
|
}
|
|
|
|
var posts map[string]Post
|
|
|
|
func LoadPosts() {
|
|
posts = map[string]Post{}
|
|
|
|
md := goldmark.New(
|
|
goldmark.WithExtensions(extension.Table, extension.Strikethrough, extension.Linkify, extension.TaskList, extension.GFM, extension.DefinitionList, extension.Footnote, extension.Typographer, meta.Meta),
|
|
goldmark.WithParserOptions(
|
|
parser.WithAutoHeadingID(),
|
|
),
|
|
)
|
|
|
|
files, err := filepath.Glob("blog/*.md")
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error reading folder")
|
|
}
|
|
|
|
for _, file := range files {
|
|
content, err := os.ReadFile(file)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg(" error reading file")
|
|
continue
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
context := parser.NewContext()
|
|
if err := md.Convert(content, &buf, parser.WithContext(context)); err != nil {
|
|
log.Fatal().Err(err)
|
|
}
|
|
metaData := meta.Get(context)
|
|
postMeta, err := MapToPostMeta(metaData)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error mapping interface to post meta")
|
|
continue
|
|
}
|
|
posts[postMeta.Slug] = Post{
|
|
Content: template.HTML(buf.String()),
|
|
Meta: postMeta,
|
|
}
|
|
|
|
}
|
|
|
|
log.Debug().Msg("loaded blog posts")
|
|
}
|
|
|
|
func blogIndexHandler(c *fiber.Ctx) error {
|
|
data := *web.Common(c)
|
|
data["Title"] = i18n.Translate(c, "blog")
|
|
data["Posts"] = posts
|
|
return c.Render("blog", data, "layouts/base")
|
|
}
|
|
|
|
func blogHandler(c *fiber.Ctx) error {
|
|
data := *web.Common(c)
|
|
data["Title"] = i18n.Translate(c, "blog")
|
|
post, ok := posts[c.Params("post")]
|
|
if !ok {
|
|
return c.Render("404", data, "layouts/base")
|
|
}
|
|
data["Post"] = post
|
|
return c.Render("post", data, "layouts/base")
|
|
}
|
|
|
|
func MapToPostMeta(m map[string]interface{}) (PostMeta, error) {
|
|
var post PostMeta
|
|
var ok bool
|
|
var err error
|
|
|
|
if post.Title, ok = m["title"].(string); !ok {
|
|
return post, fmt.Errorf("missing or invalid type for Title")
|
|
}
|
|
|
|
if post.Slug, ok = m["slug"].(string); !ok {
|
|
return post, fmt.Errorf("missing or invalid type for Title")
|
|
}
|
|
|
|
if post.Description, ok = m["description"].(string); !ok {
|
|
return post, fmt.Errorf("missing or invalid type for Description")
|
|
}
|
|
|
|
if post.Author, ok = m["author"].(string); !ok {
|
|
return post, fmt.Errorf("missing or invalid type for Author")
|
|
}
|
|
|
|
if post.Language, ok = m["language"].(string); !ok {
|
|
return post, fmt.Errorf("missing or invalid type for Language")
|
|
}
|
|
|
|
if publishDate, ok := m["publish_date"].(string); ok {
|
|
post.PublishDate, err = time.Parse("02 Jan 2006", publishDate)
|
|
if err != nil {
|
|
return post, fmt.Errorf("invalid format for PublishDate: %v", err)
|
|
}
|
|
} else {
|
|
return post, fmt.Errorf("missing or invalid type for PublishDate")
|
|
}
|
|
|
|
if updatedDate, ok := m["update_date"].(string); ok {
|
|
post.UpdatedDate, err = time.Parse("02 Jan 2006", updatedDate)
|
|
if err != nil {
|
|
return post, fmt.Errorf("invalid format for UpdatedDate: %v", err)
|
|
}
|
|
}
|
|
|
|
if tags, ok := m["tags"].([]interface{}); ok {
|
|
for _, tag := range tags {
|
|
if strTag, ok := tag.(string); ok {
|
|
post.Tags = append(post.Tags, strTag)
|
|
} else {
|
|
return post, fmt.Errorf("invalid type in Tags slice")
|
|
}
|
|
}
|
|
}
|
|
|
|
return post, nil
|
|
}
|