This commit is contained in:
2023-03-09 14:05:19 +08:00
parent b33bbad5f3
commit d145c2fd64
11 changed files with 200 additions and 69 deletions
+2 -1
View File
@@ -1 +1,2 @@
.env
.env
/data
-14
View File
@@ -1,14 +0,0 @@
## hello
```go
func getTrue() bool {
return true
}
```
Name | Age
--------|------
Bob | 27
Alice | 23
Alice | 23
-1
View File
@@ -1 +0,0 @@
# hello2
-1
View File
@@ -1 +0,0 @@
# this is go
-5
View File
@@ -1,5 +0,0 @@
# article-5
hello
this is article 5;;;
+145 -16
View File
@@ -1,42 +1,171 @@
package handler
import (
"fmt"
"bufio"
"errors"
"html/template"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/russross/blackfriday"
)
func Article(c *gin.Context) {
id := c.Param("id")
type ArticleConf struct {
Title string
Time int64
}
id = strings.Replace(id, "-", "/", -1)
type Article struct {
Id string
Uri string
Conf ArticleConf
Content string
Path string
}
articleBasePath := os.Getenv("ARTICLE_PATH")
func (a *Article) GetArticleById(id string) (*Article, error) {
path := os.Getenv("ARTICLE_PATH") + strings.Replace(id, "-", "/", -1) + ".md"
articlePath := articleBasePath + "/" + id + ".md"
return a.GetArticleByPath(path)
}
if _, err := os.Stat(articlePath); os.IsNotExist(err) {
c.String(200, "文章不存在")
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()
}
}
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]
}
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
}
// 读取Go Markdown文件
input, err := ioutil.ReadFile(articlePath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// 转换为HTML
output := blackfriday.MarkdownCommon(input)
output := blackfriday.MarkdownCommon([]byte(article.Content))
c.HTML(200, "article.html", gin.H{
"content": template.HTML(string(output)),
"title": article.Conf.Title,
})
}
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
}
+28 -26
View File
@@ -1,43 +1,45 @@
package handler
import (
"bufio"
"os"
"path/filepath"
"strings"
"strconv"
"github.com/gin-gonic/gin"
)
func Index(c *gin.Context) {
articleBasePath := os.Getenv("ARTICLE_PATH")
p, _ := strconv.Atoi(c.Query("p"))
if p < 1 {
p = 1
}
limit := 5
start := (p - 1) * limit
list := make([]string, 0)
list := make([]*Article, 0)
sortListPath := "./data/index_sort_list"
file, _ := os.Open(sortListPath)
defer file.Close()
err := filepath.Walk(articleBasePath, func(path string, info os.FileInfo, err error) error {
// 如果是目录,直接返回
if info.IsDir() {
return nil
scanner := bufio.NewScanner(file)
scanner.Scan()
total, _ := strconv.Atoi(scanner.Text())
for i := 0; i < start+limit; i++ {
scanner.Scan()
if i >= start {
id := scanner.Text()
article, err := new(Article).GetArticleById(id)
if err != nil {
continue
}
list = append(list, article)
}
// 如果文件扩展名不是 .md,直接返回
if filepath.Ext(path) != ".md" {
return nil
}
filePath := path
uri := filePath[:len(filePath)-len(filepath.Ext(filePath))]
uri = strings.Replace(uri, articleBasePath, "", -1)
uri = strings.Replace(uri, "/", "-", -1)
list = append(list, uri)
return nil
})
if err != nil {
panic(err)
}
c.HTML(200, "index.html", gin.H{
"list": list,
"list": list,
"total": total,
})
}
+20 -1
View File
@@ -2,9 +2,12 @@ package main
import (
"flag"
"gin-article/handler"
"log"
"os"
"strconv"
"sync"
"time"
"github.com/joho/godotenv"
)
@@ -26,5 +29,21 @@ func main() {
// 解析命令行参数
flag.Parse()
r.Run(":" + strconv.Itoa(*port))
var wg sync.WaitGroup
wg.Add(1)
go func() {
r.Run(":" + strconv.Itoa(*port))
}()
wg.Add(1)
go func() {
for {
handler.MakeArticleOrder()
time.Sleep(10 * time.Second)
}
}()
wg.Wait()
}
+1 -1
View File
@@ -10,7 +10,7 @@ func Router() *gin.Engine {
r := gin.Default()
r.GET("/", handler.Index)
r.GET("/article/:id", handler.Article)
r.GET("/article/:id", handler.GetArticle)
return r
}
+1 -1
View File
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="shortcut icon" href="/favicon.ico"/> -->
<title>title</title>
<title>{{ .title }}</title>
<!-- <link rel="stylesheet" href="/css/style.css"> -->
<link rel="stylesheet" href="/statics/css/github-markdown-light.css">
+3 -2
View File
@@ -5,13 +5,14 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="shortcut icon" href="/favicon.ico"/> -->
<title>title</title>
<title>Home</title>
<!-- <link rel="stylesheet" href="/css/style.css"> -->
<body>
<div>总数: {{ .total }}</div>
<ul>
{{range .list}}
<li>
<a href=" /article/{{.}}"> {{.}}</a>
<a href=" /article/{{.Id }}"> {{.Conf.Title}}</a>
</li>
{{end}}
</ul>