Files
MollyBlog/internal/mApp/mMarkdown.go

156 lines
3.2 KiB
Go

package mApp
import (
"MollyBlog/internal/storage"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"MollyBlog/internal/model"
"MollyBlog/utils"
"gopkg.in/yaml.v3"
)
// loadMarkdownFiles load markdown source files
func (ma *MApp) loadMarkdownFiles() error {
var markdownList []model.MFileInfo
var err error
markdownPath := ma.Config.Storage.SRC
switch ma.Config.Storage.Type {
case "COS":
err = storage.CosLoadMarkdowns(*ma.Config, markdownPath)
break
default:
return errors.New("Unsupported storage type: " + ma.Config.Storage.Type)
}
if err != nil {
return err
}
err = filepath.Walk(markdownPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
// filter markdown files
if filepath.Ext(path) == ".md" {
markdownList = append(markdownList, model.MFileInfo{
Name: info.Name(),
Path: path,
})
}
return nil
})
if err != nil {
return err
}
ma.SrcFiles = markdownList
return nil
}
// parseMarkdowns parse markdown files to html
func (ma *MApp) parseMarkdowns() error {
htmlPath := ma.Config.Storage.DST
for index, file := range ma.SrcFiles {
// read markdown file
_mdFile, err := os.Open(file.Path)
if err != nil {
return err
}
defer _mdFile.Close()
_mdByte, err := io.ReadAll(_mdFile)
if err != nil {
return err
}
// extract FrontMatter and clean markdown bytes
_frontMatter, _cleanBytes := utils.ExtractFrontMatter(_mdByte)
// parse frontmatter to post metadata
var post model.MPost
err = yaml.Unmarshal(_frontMatter, &post)
if err != nil {
return err
}
// convert into html format and save to html file
_htmlPath := fmt.Sprintf("%s/%s.html", htmlPath, file.Name)
_htmlFile, err := os.Create(_htmlPath)
if err != nil {
return err
}
defer _htmlFile.Close()
// set options to lute
ma.lute.SetToC(true)
_htmlByte := ma.lute.Markdown(file.Name, _cleanBytes)
_, err = _htmlFile.Write(_htmlByte)
if err != nil {
return err
}
// save html path to post's metadata
post.HtmlHash = utils.Sha256Hash(_htmlByte)
post.HtmlPath = _htmlPath
// save tags and categories to map
for _, tag := range post.Tags {
tagHash := utils.Sha256Hash([]byte(tag))
post.TagHashes = append(post.TagHashes, model.MTag{
Name: tag,
Hash: tagHash,
})
ma.Tags[tagHash] = tag
ma.TagsCount[tag] += 1
ma.TaggedPosts[tagHash] = append(ma.TaggedPosts[tagHash], &post)
model.SortPostsByDate(ma.TaggedPosts[tagHash])
}
for _, category := range post.Categories {
categoryHash := utils.Sha256Hash([]byte(category))
post.CategoryHashes = append(post.CategoryHashes, model.MCategory{
Name: category,
Hash: categoryHash,
})
ma.Categories[categoryHash] = category
ma.CategoriesCount[category] += 1
ma.CategorizedPosts[categoryHash] = append(ma.CategorizedPosts[categoryHash], &post)
model.SortPostsByDate(ma.CategorizedPosts[categoryHash])
}
// free the raw tag and category slice
post.Tags = nil
post.Categories = nil
// set post index
post.Index = uint64(index)
ma.Posts = append(ma.Posts, &post)
ma.IndexedPosts[post.Index] = &post
}
// sort Posts by date
model.SortPostsByDate(ma.Posts)
return nil
}