-
Notifications
You must be signed in to change notification settings - Fork 0
/
other.go
191 lines (158 loc) · 4.61 KB
/
other.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
182
183
184
185
186
187
188
189
190
191
package structs
import (
"time"
"gopkg.in/yaml.v3"
)
type PageData struct {
OutputPath string
CurrentPath string
Dir string
Breadcrumbs []Dir
Panels Panels
Content *Content
Timestamp int64
Connections Connections
}
// Contents represents a list of contents, where key is a file path.
// It is used to properly render references.
type Contents map[string]Content
// Connections represents a list of connectiones that initiated by a reference.
// Key is a file path, where reference is pointing to.
// Value is a map, where key is a file path, where reference is located,
// and value is a type of reference.
// For example, three files "Alice", "Book" and "Cinema" are referencing to file "Dave",
// but in different contexts. File "Alice" just has a reference to file "Dave",
// file "Book" has a reference "Dave" as an "Author",
// and file "Cinema" has a reference "Dave" as a "Voice" for "Bob" (presumably, a character).
// Then the Connections map will look like this:
//
// {
// "Dave": {
// "Alice": []
// "Book": ["Author"]
// "Cinema": ["Voice", "Bob"],
// }
// }
//
// In case of TV series, it's a bit more complicated, because there are multiple episodes.
// The problem is that same person can be a writer for a multiple episodes.
// And when adding connection for the same person to the same content, it will append to the list.
//
// {
// "Charlie Brooker": {
// "Black Mirror": [
// "Writer", "", "The National Anthem",
// "Writer", "", "Fifteen Million Merits",
// "Writer", "", "The Entire History of You",
// ],
// }
// }
type Connections map[string]map[string][]string
type Columns map[string]string
func (c *Columns) Add(key, value string) {
if *c == nil {
*c = make(map[string]string)
}
if value == "" {
return
}
(*c)[key] = value
}
func (c *Columns) Get(key string) string {
if *c == nil {
return ""
}
if value, ok := (*c)[key]; ok {
return value
}
return ""
}
// File represents a file or directory in the file system.
type File struct {
Name string
Title string // value from YAML "name" field, may contain colons
IsFolder bool // used to render folder icon and to sort files
IsMissing bool // for pages that have no source file; used to show striped background
Image *Media
Columns Columns // extra fields to use in list view
}
// ByNameFolderOnTop sorts files by name, with folders on top.
type ByNameFolderOnTop []File
func (a ByNameFolderOnTop) Len() int { return len(a) }
func (a ByNameFolderOnTop) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByNameFolderOnTop) Less(i, j int) bool {
if a[i].IsFolder == a[j].IsFolder {
return a[i].Name < a[j].Name
}
if a[i].IsFolder && !a[j].IsFolder {
return true
}
if !a[i].IsFolder && a[j].IsFolder {
return false
}
return a[i].Name < a[j].Name
}
// ByYearDesk sorts files by year, with newest on top.
// Directories that does not match the year format are sorted alphabetically.
type ByYearDesk []File
func (f ByYearDesk) Len() int { return len(f) }
func (f ByYearDesk) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f ByYearDesk) Less(i, j int) bool {
a, err := time.Parse("2006", f[i].Name)
aIsYear := err == nil
b, err := time.Parse("2006", f[j].Name)
bIsYear := err == nil
if aIsYear && bIsYear {
return a.After(b)
}
if aIsYear && !bIsYear {
return false
}
if !aIsYear && bIsYear {
return true
}
return ByNameFolderOnTop(f).Less(i, j)
}
// Panel represents a single directory with files.
type Panel struct {
Dir string
Files []File
}
// Dir represents a directory in the breadcrumbs.
type Dir struct {
Name string
Path string
}
// FileLists is a map, where key is a directory path, and value is a Panel that corresponds to that directory.
type FileLists map[string]Panel
// Panels represents a list of panels.
type Panels []Panel
// Breadcrumbs represents a list of directories in the breadcrumbs.
type Breadcrumbs []Dir
// Reference represents a reference to another file.
// Often it has only a path.
type Reference struct {
Path string
Name string
}
// UnmarshalYAML is a custom unmarshaler for Reference.
// It can be either a string or a map.
func (r *Reference) UnmarshalYAML(value *yaml.Node) error {
if value.Kind == yaml.ScalarNode {
r.Path = value.Value
return nil
}
return value.Decode(&r)
}
// Missing represents a missing reference.
// Used in "missing" template function to render Missing.gomd file.
type Missing struct {
To string
From map[string][]string
Awards []Award
}
// Extra usind in "splitExtra" template function to separate episode titles from the rest of the data.
type Extra struct {
Primary []string
Addon string
}