forked from go-xiaohei/pugo
/
meta.go
181 lines (166 loc) · 4.06 KB
/
meta.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package model
import (
"errors"
"fmt"
"net/url"
"path"
"strings"
"github.com/BurntSushi/toml"
"gopkg.in/ini.v1"
)
type (
// Meta is meta info of website
Meta struct {
Title string `toml:"title" ini:"title"`
Subtitle string `toml:"subtitle" ini:"subtitle"`
Keyword string `toml:"keyword" ini:"keyword"`
Desc string `toml:"desc" ini:"desc"`
Domain string `toml:"domain" ini:"domain"`
Root string `toml:"root" ini:"root"`
Cover string `toml:"cover" ini:"cover"`
Language string `toml:"lang" ini:"lang"`
Path string `toml:"-" ini:"-"`
}
// MetaAll is all data struct in meta file
MetaAll struct {
Meta *Meta `toml:"meta"`
NavGroup NavGroup `toml:"nav"`
AuthorGroup AuthorGroup `toml:"author"`
Comment *Comment `toml:"comment"`
Analytics *Analytics `toml:"analytics"`
Build *Build `toml:"build"`
}
)
var (
errMetaUnsupport = errors.New("meta file format is unsupported")
errMetaInvalid = errors.New("meta title and (root or domain) cant be blank")
)
// NewMetaAll parse bytes with correct FormatType
func NewMetaAll(data []byte, format FormatType) (*MetaAll, error) {
var err error
switch format {
case FormatTOML:
meta := &MetaAll{}
if err = toml.Unmarshal(data, meta); err != nil {
return nil, err
}
if err = meta.Normalize(); err != nil {
return nil, err
}
return meta, nil
case FormatINI:
return newMetaAllFromINI(data)
}
return nil, errMetaUnsupport
}
func newMetaAllFromINI(data []byte) (*MetaAll, error) {
iniObj, err := ini.Load(data)
if err != nil {
return nil, err
}
section := iniObj.Section("meta")
metaAll := new(MetaAll)
// parse meta block
meta := new(Meta)
if err = section.MapTo(meta); err != nil {
return nil, err
}
metaAll.Meta = meta
// read navigation
var (
navGroup []*Nav
sectionName string
)
navKeys := iniObj.Section("nav").Keys()
for _, k := range navKeys {
sectionName = "nav." + k.Value()
nav := new(Nav)
if err = iniObj.Section(sectionName).MapTo(nav); err != nil {
return nil, err
}
if nav.Title == "" && nav.Link == "" {
continue
}
navGroup = append(navGroup, nav)
}
metaAll.NavGroup = navGroup
// read author
var authorGroup []*Author
authorKeys := iniObj.Section("author").Keys()
for _, k := range authorKeys {
sectionName = "author." + k.Value()
author := new(Author)
if err = iniObj.Section(sectionName).MapTo(author); err != nil {
return nil, err
}
if author.Name == "" {
continue
}
authorGroup = append(authorGroup, author)
}
metaAll.AuthorGroup = authorGroup
// read comment and analytics and build settings
cmt := new(Comment)
if err := iniObj.Section("comment").MapTo(cmt); err != nil {
return nil, err
}
any := new(Analytics)
if err := iniObj.Section("analytics").MapTo(cmt); err != nil {
return nil, err
}
build := new(Build)
if err := iniObj.Section("build").MapTo(build); err != nil {
return nil, err
}
metaAll.Comment = cmt
metaAll.Analytics = any
metaAll.Build = build
if err = metaAll.Normalize(); err != nil {
return nil, err
}
return metaAll, nil
}
// DomainURL return link with domain prefix
func (m *Meta) DomainURL(link string) string {
link = strings.TrimPrefix(link, m.Path)
link = strings.Trim(link, "/")
return fmt.Sprintf("http://%s/%s", m.Domain, path.Join(strings.Trim(m.Path, "/"), link))
}
func (m *Meta) normalize() error {
if (m.Root == "" && m.Domain == "") || m.Title == "" {
return errMetaInvalid
}
if m.Root == "" && m.Domain != "" {
m.Root = "http://" + m.Domain + "/"
}
u, err := url.Parse(m.Root)
if err != nil {
return err
}
if m.Domain == "" {
m.Domain = u.Host
}
m.Path = u.Path
if m.Desc == "" {
m.Desc = m.Title
}
if m.Keyword == "" {
m.Keyword = m.Title
}
return nil
}
// Normalize make meta all data correct,
// it fills blank fields to correct values
func (ma *MetaAll) Normalize() error {
var err error
if err = ma.Meta.normalize(); err != nil {
return err
}
if err = ma.NavGroup.normalize(); err != nil {
return err
}
if err = ma.AuthorGroup.normalize(); err != nil {
return err
}
return nil
}