Files
2023-04-21 14:13:23 +08:00

176 lines
3.5 KiB
Go

package handler
import (
"bufio"
"errors"
"html/template"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/russross/blackfriday"
)
type ArticleConf struct {
Title string
Time int64
}
type Article struct {
Id string
Uri string
Conf ArticleConf
Content string
Path string
Date string
}
func (a *Article) GetArticleById(id string) (*Article, error) {
path := os.Getenv("ARTICLE_PATH") + strings.Replace(id, "<-", "/", -1) + ".md"
return a.GetArticleByPath(path)
}
func (a *Article) GetArticleByPath(path string) (*Article, error) {
a.Path = path
a.Uri = strings.Replace(a.Path, os.Getenv("ARTICLE_PATH"), "", -1)
a.Id = a.Uri[:len(a.Uri)-len(filepath.Ext(a.Uri))]
a.Id = strings.Replace(a.Id, "\\", "/", -1)
a.Id = strings.Replace(a.Id, "/", "<-", -1)
// 读取文件内容
fileByte, err := ioutil.ReadFile(a.Path)
if err != nil {
return a, errors.New("文章不存在")
}
parts := strings.Split(string(fileByte), "<-->")
var articleConf map[string]string
if len(parts) == 2 {
if len(parts[0]) > 0 {
articleConf = GetArticleConf(parts[0])
if len(articleConf["date"]) > 0 {
t, err := time.Parse("2006-1-2 15:04", articleConf["date"])
if err == nil {
a.Conf.Time = t.Unix()
a.Date = time.Unix(a.Conf.Time, 0).Format("2006-01-02")
}
}
if len(articleConf["title"]) > 0 {
a.Conf.Title = articleConf["title"]
}
}
a.Content = parts[1]
} else {
a.Conf.Title = a.Id
info, _ := os.Stat(a.Path)
mtime := info.ModTime()
a.Conf.Time = mtime.Unix()
a.Content = parts[0]
a.Date = time.Unix(a.Conf.Time, 0).Format("2006-01-02")
}
return a, nil
}
func GetArticle(c *gin.Context) {
article, err := new(Article).GetArticleById(c.Param("id"))
if err != nil {
c.String(200, err.Error())
return
}
// 转换为HTML
output := blackfriday.MarkdownCommon([]byte(article.Content))
c.HTML(200, "article.html", gin.H{
"content": template.HTML(string(output)),
"title": article.Conf.Title,
"date": article.Date,
})
}
func MakeArticleOrder() {
articleBasePath := os.Getenv("ARTICLE_PATH")
list := make(map[string]int64)
aritcleNew := new(Article)
_ = filepath.Walk(articleBasePath, func(path string, info os.FileInfo, err error) error {
if info.IsDir() || filepath.Ext(path) != ".md" {
return nil
}
article, err := aritcleNew.GetArticleByPath(path)
if err != nil {
return nil
}
list[article.Id] = article.Conf.Time
return nil
})
if len(list) == 0 {
return
}
sortList := sortArticleByTime(list)
filename := "./data/index_sort_list"
file, err := os.Create(filename)
if err != nil {
return
}
defer file.Close()
writer := bufio.NewWriter(file)
total := len(sortList)
writer.WriteString(strconv.Itoa(total) + "\n")
for _, info := range sortList {
writer.WriteString(info.Title + "\n")
}
writer.Flush()
}
func GetArticleConf(conf string) map[string]string {
data := make(map[string]string)
conf = strings.Replace(conf, "\r\n", "\n", -1)
list := strings.Split(conf, "\n")
for _, conf := range list {
index := strings.Index(conf, ":")
if index == -1 {
continue
}
key := conf[0:index]
value := conf[index+1:]
data[key] = value
}
return data
}
func sortArticleByTime(m map[string]int64) []ArticleConf {
pairs := make([]ArticleConf, 0, len(m))
for k, v := range m {
pairs = append(pairs, ArticleConf{k, v})
}
// 对结构体切片按照值进行排序
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].Time > pairs[j].Time
})
return pairs
}