feat: datasource with yaml
This commit is contained in:
parent
2e55397574
commit
eae87c0365
@ -1,8 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func deployCmd() *cobra.Command {
|
func deployCmd() *cobra.Command {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -17,6 +16,8 @@ import (
|
|||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
"github.com/yuin/goldmark/text"
|
"github.com/yuin/goldmark/text"
|
||||||
"go.abhg.dev/goldmark/toc"
|
"go.abhg.dev/goldmark/toc"
|
||||||
|
|
||||||
|
"gitter.top/mder/mder/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateCmd() *cobra.Command {
|
func generateCmd() *cobra.Command {
|
||||||
@ -39,10 +40,12 @@ func generateCmd() *cobra.Command {
|
|||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// 读取资源文件
|
// 读取资源文件
|
||||||
if err := outter.readDataSource(); err != nil {
|
dataSource, err := internal.GetDataSource(BaseDir)
|
||||||
logger.Errorf("read data source failed: %v", err)
|
if err != nil {
|
||||||
|
logger.Fatalf("get data source failed: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
outter.DataSource = dataSource
|
||||||
// 读取主题模板文件
|
// 读取主题模板文件
|
||||||
if err := outter.readTheme(outter.Config.Site.Theme); err != nil {
|
if err := outter.readTheme(outter.Config.Site.Theme); err != nil {
|
||||||
logger.Errorf("read theme source failed: %v", err)
|
logger.Errorf("read theme source failed: %v", err)
|
||||||
@ -63,7 +66,7 @@ func generateCmd() *cobra.Command {
|
|||||||
},
|
},
|
||||||
PostRun: func(cmd *cobra.Command, args []string) {
|
PostRun: func(cmd *cobra.Command, args []string) {
|
||||||
endAt := time.Since(startAt)
|
endAt := time.Since(startAt)
|
||||||
logger.Infof("generate used: %s", endAt.String())
|
logger.Infof("generate cost: %s", endAt.String())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringVar(&path, "path", ".", "mder project path")
|
cmd.Flags().StringVar(&path, "path", ".", "mder project path")
|
||||||
@ -295,7 +298,7 @@ func (o *Outter) readTheme(themeName string) (err error) {
|
|||||||
type Outter struct {
|
type Outter struct {
|
||||||
SourceVersion string // 资源号 防缓存
|
SourceVersion string // 资源号 防缓存
|
||||||
Config *Config // 全局配置
|
Config *Config // 全局配置
|
||||||
SourceData map[string]interface{} // 记录source/data下的所有文件
|
DataSource internal.DataSource // 记录source/data下的所有文件
|
||||||
Posts []*Post // 记录文章
|
Posts []*Post // 记录文章
|
||||||
DraftPosts []*Post // 不宜发布的草稿文章
|
DraftPosts []*Post // 不宜发布的草稿文章
|
||||||
Pages []*Page // 记录页面
|
Pages []*Page // 记录页面
|
||||||
@ -352,38 +355,6 @@ func (o *Outter) loadConfig() error {
|
|||||||
return o.Config.load()
|
return o.Config.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// readDataSource 读取资源文件
|
|
||||||
func (o *Outter) readDataSource() error {
|
|
||||||
o.SourceData = make(map[string]interface{})
|
|
||||||
var dataDir = BaseDir + "/data"
|
|
||||||
dirs, err := os.ReadDir(dataDir)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, dir := range dirs {
|
|
||||||
if dir.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 不是json文件
|
|
||||||
if !strings.HasSuffix(dir.Name(), ".json") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var body []byte
|
|
||||||
body, err = os.ReadFile(fmt.Sprintf("%s/%s", dataDir, dir.Name()))
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("read data source file failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var obj interface{}
|
|
||||||
if err := json.Unmarshal(body, &obj); err != nil {
|
|
||||||
logger.Errorf("unmarshal data source file failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.SourceData[strings.ReplaceAll(dir.Name(), ".json", "")] = obj
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate 文件生成
|
// generate 文件生成
|
||||||
func (o *Outter) generate() {
|
func (o *Outter) generate() {
|
||||||
// 清理dist目录
|
// 清理dist目录
|
||||||
@ -916,12 +887,8 @@ var funcMap = template.FuncMap{
|
|||||||
"sum": sum,
|
"sum": sum,
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSource(data interface{}, key string) interface{} {
|
func getSource(data internal.DataSource, key string) []*internal.DataItem {
|
||||||
source, ok := data.(map[string]interface{})
|
return data[key]
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return source[key]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(a, b int) int {
|
func add(a, b int) int {
|
||||||
|
|||||||
44
go.mod
44
go.mod
@ -3,47 +3,49 @@ module gitter.top/mder/mder
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/guonaihong/gout v0.3.9
|
github.com/guonaihong/gout v0.3.10
|
||||||
github.com/radovskyb/watcher v1.0.7
|
github.com/radovskyb/watcher v1.0.7
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.1
|
||||||
github.com/yuin/goldmark v1.6.0
|
github.com/yuin/goldmark v1.7.4
|
||||||
github.com/yuin/goldmark-emoji v1.0.2
|
github.com/yuin/goldmark-emoji v1.0.3
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
github.com/yuin/goldmark-meta v1.1.0
|
||||||
go.abhg.dev/goldmark/mermaid v0.5.0
|
go.abhg.dev/goldmark/mermaid v0.5.0
|
||||||
go.abhg.dev/goldmark/toc v0.9.0
|
go.abhg.dev/goldmark/toc v0.10.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/bytedance/sonic v1.10.2 // indirect
|
github.com/bytedance/sonic v1.12.2 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.17.0 // indirect
|
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||||
github.com/leodido/go-urn v1.3.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/samber/lo v1.47.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
golang.org/x/arch v0.7.0 // indirect
|
golang.org/x/arch v0.10.0 // indirect
|
||||||
golang.org/x/crypto v0.18.0 // indirect
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
golang.org/x/net v0.20.0 // indirect
|
golang.org/x/net v0.29.0 // indirect
|
||||||
golang.org/x/sys v0.16.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
google.golang.org/protobuf v1.32.0 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
47
internal/read_data.go
Normal file
47
internal/read_data.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DataItem struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Link string `yaml:"link"`
|
||||||
|
Desc string `yaml:"desc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataSource map[string][]*DataItem
|
||||||
|
|
||||||
|
// GetDataSource 读取数据目录 数据目录不支持嵌套读入
|
||||||
|
func GetDataSource(dir string) (DataSource, error) {
|
||||||
|
dir = filepath.Join(dir, "data")
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var datasource = make(DataSource)
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 不是json文件
|
||||||
|
ext := filepath.Ext(entry.Name())
|
||||||
|
// 没有指定扩展名
|
||||||
|
if ext == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !lo.Contains([]string{".yaml", ".yml"}, ext) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filename := entry.Name()[:len(entry.Name())-len(filepath.Ext(entry.Name()))]
|
||||||
|
dataItems, err := ReadYamlToDataItems(filepath.Join(dir, entry.Name()))
|
||||||
|
if err != nil {
|
||||||
|
panic("read data source file failed: " + err.Error())
|
||||||
|
}
|
||||||
|
datasource[filename] = dataItems
|
||||||
|
}
|
||||||
|
return datasource, nil
|
||||||
|
}
|
||||||
25
internal/read_page.go
Normal file
25
internal/read_page.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Post 文章属性
|
||||||
|
type Post struct {
|
||||||
|
Title string // 文章标题
|
||||||
|
FileBasename string // 文件名
|
||||||
|
Link string // 链接
|
||||||
|
Category string // 分类
|
||||||
|
CategoryAlias string // 分类别名
|
||||||
|
Tags []string // 标签
|
||||||
|
CreatedAt time.Time // 创建时间
|
||||||
|
CreatedAtFormat string // 创建时间格式化
|
||||||
|
UpdatedAtFormat string // 更新时间
|
||||||
|
MD string // 文章内容
|
||||||
|
TOC string // 文章toc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page 页面属性
|
||||||
|
type Page struct {
|
||||||
|
Title string // 展示名
|
||||||
|
Link string // 链接名
|
||||||
|
MD string // 页面内容
|
||||||
|
}
|
||||||
17
internal/utils.go
Normal file
17
internal/utils.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadYamlToDataItems(filename string) ([]*DataItem, error) {
|
||||||
|
readFile, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var dataItems []*DataItem
|
||||||
|
err = yaml.Unmarshal(readFile, &dataItems)
|
||||||
|
return dataItems, err
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@ func serveCmd() *cobra.Command {
|
|||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "serve",
|
Use: "serve",
|
||||||
Short: "run a serve locally",
|
Short: "run a serve locally",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
w := watcher.New()
|
w := watcher.New()
|
||||||
w.SetMaxEvents(1)
|
w.SetMaxEvents(1)
|
||||||
@ -73,9 +74,9 @@ func serveCmd() *cobra.Command {
|
|||||||
logger.Errorf("generate website failed: %v", err)
|
logger.Errorf("generate website failed: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 五秒一次
|
// 3秒一次
|
||||||
logger.Info("http://127.0.0.1:8666")
|
logger.Info("http://127.0.0.1:8666")
|
||||||
if err := w.Start(time.Second * 5); err != nil {
|
if err := w.Start(time.Second * 3); err != nil {
|
||||||
logger.Errorf("watch file failed: %v", err)
|
logger.Errorf("watch file failed: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ func updateCmd() *cobra.Command {
|
|||||||
Use: "update",
|
Use: "update",
|
||||||
Short: "mder auto update",
|
Short: "mder auto update",
|
||||||
Example: "mder update",
|
Example: "mder update",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
commit, err := GetRepoLatestCommit()
|
commit, err := GetRepoLatestCommit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user