forked from bakape/shamichan
/
article.go
119 lines (104 loc) · 2.74 KB
/
article.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
package templates
import (
"html"
"meguca/common"
"meguca/lang"
"strconv"
"time"
)
// Extra data passed, when rendering an article
type articleContext struct {
index, sticky bool
omit, imageOmit int
op uint64
board, subject, root string
backlinks backlinks
}
// Map of all backlinks on a page
type backlinks map[uint64]map[uint64]uint64
// Returns image name with proper extension
func imageName(fileType uint8, name string) string {
ext := common.Extensions[fileType]
l := len(name)
buf := make([]byte, l, l+1+len(ext))
copy(buf, name)
buf = append(buf, '.')
return html.EscapeString(string(append(buf, ext...)))
}
// Renders the post creation time field
func formatTime(sec int64) string {
ln := lang.Get().Common.Time
t := time.Unix(sec, 0)
year, m, day := t.Date()
weekday := ln["week"][int(t.Weekday())]
// Months are 1-indexed for some fucking reason
month := ln["calendar"][int(m)-1]
// Premature optimization
buf := make([]byte, 0, 17+len(weekday)+len(month))
buf = pad(buf, day)
buf = append(buf, ' ')
buf = append(buf, month...)
buf = append(buf, ' ')
buf = append(buf, strconv.Itoa(year)...)
buf = append(buf, " ("...)
buf = append(buf, weekday...)
buf = append(buf, ") "...)
buf = pad(buf, t.Hour())
buf = append(buf, ':')
buf = pad(buf, t.Minute())
return string(buf)
}
// Stringify an int and left-pad to at least double digits
func pad(buf []byte, i int) []byte {
if i < 10 {
buf = append(buf, '0')
}
return append(buf, strconv.Itoa(i)...)
}
// Formats a human-readable representation of file size
func readableFileSize(s int) string {
format := func(n, end string) string {
l := len(n)
buf := make([]byte, l, l+len(end))
copy(buf, n)
return string(append(buf, end...))
}
switch {
case s < (1 << 10):
return format(strconv.Itoa(s), " B")
case s < (1 << 20):
return format(strconv.Itoa(s/(1<<10)), " KB")
default:
n := strconv.FormatFloat(float64(s)/(1<<20), 'f', 1, 32)
return format(n, " MB")
}
}
// Correct thumbnail dimensions for smaller reply thumbnails
func correctDims(large bool, w, h uint16) (string, string) {
if !large && (w > 125 || h > 125) {
w = uint16(float32(w) * 0.8333)
h = uint16(float32(h) * 0.8333)
}
return strconv.FormatUint(uint64(w), 10), strconv.FormatUint(uint64(h), 10)
}
// Extract reverse links to linked posts on a page
func extractBacklinks(cap int, threads ...common.Thread) backlinks {
bls := make(backlinks, cap)
register := func(p common.Post, op uint64) {
for _, l := range p.Links {
m, ok := bls[l[0]]
if !ok {
m = make(map[uint64]uint64, 4)
bls[l[0]] = m
}
m[p.ID] = op
}
}
for _, t := range threads {
register(t.Post, t.ID)
for _, p := range t.Posts {
register(p, t.ID)
}
}
return bls
}