From 7c20b472f65656f7fb2d7ede17c822ca4272ce06 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Thu, 13 Jul 2023 20:39:24 +0200 Subject: [PATCH] importer + markdown --- app/binary_service.go | 4 ++ cmd/owl/import_v1.go | 67 ++++++++++++++++++++++++++--- domain/model/image.go | 3 +- go.mod | 1 + go.sum | 2 + importer/utils.go | 8 +++- render/templates.go | 42 +++++++++++++++--- render/templates/entry/Article.tmpl | 2 +- web/index_handler.go | 6 +++ 9 files changed, 118 insertions(+), 17 deletions(-) diff --git a/app/binary_service.go b/app/binary_service.go index e2b8949..d459cd8 100644 --- a/app/binary_service.go +++ b/app/binary_service.go @@ -17,6 +17,10 @@ func (s *BinaryService) Create(name string, file []byte) (*model.BinaryFile, err return s.repo.Create(name, file, nil) } +func (s *BinaryService) CreateEntryFile(name string, file []byte, entry model.Entry) (*model.BinaryFile, error) { + return s.repo.Create(name, file, entry) +} + func (s *BinaryService) FindById(id string) (*model.BinaryFile, error) { return s.repo.FindById(id) } diff --git a/cmd/owl/import_v1.go b/cmd/owl/import_v1.go index 5a02868..69f9b42 100644 --- a/cmd/owl/import_v1.go +++ b/cmd/owl/import_v1.go @@ -2,9 +2,11 @@ package main import ( "fmt" + "os" "owl-blogs/domain/model" "owl-blogs/importer" "owl-blogs/infra" + "path" "github.com/spf13/cobra" ) @@ -32,30 +34,81 @@ var importCmd = &cobra.Command{ } for _, post := range posts { + existing, _ := app.EntryService.FindById(post.Id) + if existing != nil { + continue + } fmt.Println(post.Meta.Type) + + // import assets + mediaDir := path.Join(userPath, post.MediaDir()) + println(mediaDir) + files := importer.ListDir(mediaDir) + for _, file := range files { + // mock entry to pass to binary service + entry := &model.Article{} + entry.SetID(post.Id) + + fileData, err := os.ReadFile(path.Join(mediaDir, file)) + if err != nil { + panic(err) + } + app.BinaryService.CreateEntryFile(file, fileData, entry) + } + switch post.Meta.Type { case "article": article := model.Article{} article.SetID(post.Id) - article.SetMetaData(model.ArticleMetaData{ + article.SetPublishedAt(&post.Meta.Date) + article.SetMetaData(&model.ArticleMetaData{ Title: post.Meta.Title, Content: post.Content, }) - article.SetPublishedAt(&post.Meta.Date) app.EntryService.Create(&article) - case "bookmark": case "reply": case "photo": - + photo := model.Image{} + photo.SetID(post.Id) + photo.SetPublishedAt(&post.Meta.Date) + photo.SetMetaData(&model.ImageMetaData{ + Title: post.Meta.Title, + Content: post.Content, + ImageId: post.Meta.PhotoPath, + }) + app.EntryService.Create(&photo) case "note": - + note := model.Note{} + note.SetID(post.Id) + note.SetPublishedAt(&post.Meta.Date) + note.SetMetaData(&model.NoteMetaData{ + Content: post.Content, + }) + app.EntryService.Create(¬e) case "recipe": - + recipe := model.Recipe{} + recipe.SetID(post.Id) + recipe.SetPublishedAt(&post.Meta.Date) + recipe.SetMetaData(&model.RecipeMetaData{ + Title: post.Meta.Title, + Yield: post.Meta.Recipe.Yield, + Duration: post.Meta.Recipe.Duration, + Ingredients: post.Meta.Recipe.Ingredients, + Content: post.Content, + }) + app.EntryService.Create(&recipe) case "page": - + page := model.Page{} + page.SetID(post.Id) + page.SetPublishedAt(&post.Meta.Date) + page.SetMetaData(&model.PageMetaData{ + Title: post.Meta.Title, + Content: post.Content, + }) + app.EntryService.Create(&page) default: panic("Unknown type") } diff --git a/domain/model/image.go b/domain/model/image.go index 176d8a5..cc77ca5 100644 --- a/domain/model/image.go +++ b/domain/model/image.go @@ -12,11 +12,12 @@ type Image struct { type ImageMetaData struct { ImageId string `owl:"inputType=file"` + Title string `owl:"inputType=text"` Content string `owl:"inputType=text widget=textarea"` } func (e *Image) Title() string { - return "" + return e.meta.Title } func (e *Image) Content() EntryContent { diff --git a/go.mod b/go.mod index 54cae65..8496677 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.47.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + github.com/yuin/goldmark v1.5.4 // indirect golang.org/x/crypto v0.11.0 // indirect golang.org/x/sys v0.10.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index a5aaeef..8656157 100644 --- a/go.sum +++ b/go.sum @@ -62,6 +62,8 @@ github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVS github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU= +github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/importer/utils.go b/importer/utils.go index 15bf9e2..e7fe2c1 100644 --- a/importer/utils.go +++ b/importer/utils.go @@ -43,6 +43,10 @@ type Post struct { Content string } +func (post *Post) MediaDir() string { + return path.Join("public", post.Id, "media") +} + func (pm *PostMeta) UnmarshalYAML(unmarshal func(interface{}) error) error { type T struct { Type string `yaml:"type"` @@ -155,7 +159,7 @@ func LoadMeta(data []byte) (PostMeta, error) { } func AllUserPosts(userPath string) ([]Post, error) { - postFiles := listDir(path.Join(userPath, "public")) + postFiles := ListDir(path.Join(userPath, "public")) posts := make([]Post, 0) for _, id := range postFiles { // if is a directory and has index.md, add to posts @@ -182,7 +186,7 @@ func AllUserPosts(userPath string) ([]Post, error) { return posts, nil } -func listDir(path string) []string { +func ListDir(path string) []string { dir, _ := os.Open(path) defer dir.Close() files, _ := dir.Readdirnames(-1) diff --git a/render/templates.go b/render/templates.go index 251168b..a9a88ce 100644 --- a/render/templates.go +++ b/render/templates.go @@ -5,19 +5,33 @@ import ( "embed" "io" "text/template" + + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/extension" + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/renderer/html" ) //go:embed templates var templates embed.FS +var funcMap = template.FuncMap{ + "markdown": func(text string) string { + html, err := RenderMarkdown(text) + if err != nil { + return ">>>could not render markdown<<<" + } + return html + }, +} + func CreateTemplateWithBase(templateName string) (*template.Template, error) { - return template.ParseFS( + return template.New(templateName).Funcs(funcMap).ParseFS( templates, "templates/base.tmpl", "templates/"+templateName+".tmpl", ) - } func RenderTemplateWithBase(w io.Writer, templateName string, data interface{}) error { @@ -35,11 +49,9 @@ func RenderTemplateWithBase(w io.Writer, templateName string, data interface{}) } func RenderTemplateToString(templateName string, data interface{}) (string, error) { + tmplStr, _ := templates.ReadFile("templates/" + templateName + ".tmpl") - t, err := template.ParseFS( - templates, - "templates/"+templateName+".tmpl", - ) + t, err := template.New("templates/" + templateName + ".tmpl").Funcs(funcMap).Parse(string(tmplStr)) if err != nil { return "", err @@ -50,3 +62,21 @@ func RenderTemplateToString(templateName string, data interface{}) (string, erro err = t.Execute(&output, data) return output.String(), err } + +func RenderMarkdown(mdText string) (string, error) { + markdown := goldmark.New( + goldmark.WithRendererOptions( + html.WithUnsafe(), + ), + goldmark.WithExtensions( + // meta.Meta, + extension.GFM, + ), + ) + var buf bytes.Buffer + context := parser.NewContext() + err := markdown.Convert([]byte(mdText), &buf, parser.WithContext(context)) + + return buf.String(), err + +} diff --git a/render/templates/entry/Article.tmpl b/render/templates/entry/Article.tmpl index bac8848..f9e080a 100644 --- a/render/templates/entry/Article.tmpl +++ b/render/templates/entry/Article.tmpl @@ -1 +1 @@ -{{.MetaData.Content}} +{{.MetaData.Content | markdown }} diff --git a/web/index_handler.go b/web/index_handler.go index 2a0575d..ae4fa64 100644 --- a/web/index_handler.go +++ b/web/index_handler.go @@ -3,6 +3,7 @@ package web import ( "owl-blogs/app" "owl-blogs/render" + "sort" "github.com/gofiber/fiber/v2" ) @@ -19,6 +20,11 @@ func (h *IndexHandler) Handle(c *fiber.Ctx) error { c.Set(fiber.HeaderContentType, fiber.MIMETextHTML) entries, err := h.entrySvc.FindAll() + // sort entries by date descending + sort.Slice(entries, func(i, j int) bool { + return entries[i].PublishedAt().After(*entries[j].PublishedAt()) + }) + if err != nil { return err }