Feature: decorate the tag container
This commit is contained in:
parent
d9396ba671
commit
f3f373f73f
|
@ -3,144 +3,178 @@ package handler
|
|||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"pixivfe/configs"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/template/jet/v2"
|
||||
)
|
||||
|
||||
func GetTemplateFunctions(engine *jet.Engine) {
|
||||
engine.AddFunc("inc", func(n int) int {
|
||||
// For rankings to increment a number by 1
|
||||
return n + 1
|
||||
})
|
||||
engine.AddFunc("add", func(a int, b int) int {
|
||||
return a + b
|
||||
})
|
||||
func GetRandomColor() string {
|
||||
// Some color shade I stole
|
||||
colors := []string{
|
||||
// Green
|
||||
"#C8847E",
|
||||
"#C8A87E",
|
||||
"#C8B87E",
|
||||
"#C8C67E",
|
||||
"#C7C87E",
|
||||
"#C2C87E",
|
||||
"#BDC87E",
|
||||
"#82C87E",
|
||||
"#82C87E",
|
||||
"#7EC8AF",
|
||||
"#7EAEC8",
|
||||
"#7EA6C8",
|
||||
"#7E99C8",
|
||||
"#7E87C8",
|
||||
"#897EC8",
|
||||
"#967EC8",
|
||||
"#AE7EC8",
|
||||
"#B57EC8",
|
||||
"#C87EA5",
|
||||
}
|
||||
|
||||
engine.AddFunc("dec", func(n int) int {
|
||||
return n - 1
|
||||
})
|
||||
|
||||
engine.AddFunc("toInt", func(s string) int {
|
||||
n, _ := strconv.Atoi(s)
|
||||
return n
|
||||
})
|
||||
|
||||
engine.AddFunc("proxyImage", func(url string) string {
|
||||
if strings.Contains(url, "s.pximg.net") {
|
||||
// This subdomain didn't get proxied
|
||||
return url
|
||||
}
|
||||
|
||||
regex := regexp.MustCompile(`.*?pximg\.net`)
|
||||
proxy := "https://" + configs.ProxyServer
|
||||
|
||||
return regex.ReplaceAllString(url, proxy)
|
||||
})
|
||||
engine.AddFunc("parseEmojis", func(s string) template.HTML {
|
||||
regex := regexp.MustCompile(`\(([^)]+)\)`)
|
||||
|
||||
parsedString := regex.ReplaceAllStringFunc(s, func(s string) string {
|
||||
s = s[1 : len(s)-1] // Get the string inside
|
||||
var id string
|
||||
|
||||
switch s {
|
||||
case "normal":
|
||||
id = "101"
|
||||
case "surprise":
|
||||
id = "102"
|
||||
case "serious":
|
||||
id = "103"
|
||||
case "heaven":
|
||||
id = "104"
|
||||
case "happy":
|
||||
id = "105"
|
||||
case "excited":
|
||||
id = "106"
|
||||
case "sing":
|
||||
id = "107"
|
||||
case "cry":
|
||||
id = "108"
|
||||
case "normal2":
|
||||
id = "201"
|
||||
case "shame2":
|
||||
id = "202"
|
||||
case "love2":
|
||||
id = "203"
|
||||
case "interesting2":
|
||||
id = "204"
|
||||
case "blush2":
|
||||
id = "205"
|
||||
case "fire2":
|
||||
id = "206"
|
||||
case "angry2":
|
||||
id = "207"
|
||||
case "shine2":
|
||||
id = "208"
|
||||
case "panic2":
|
||||
id = "209"
|
||||
case "normal3":
|
||||
id = "301"
|
||||
case "satisfaction3":
|
||||
id = "302"
|
||||
case "surprise3":
|
||||
id = "303"
|
||||
case "smile3":
|
||||
id = "304"
|
||||
case "shock3":
|
||||
id = "305"
|
||||
case "gaze3":
|
||||
id = "306"
|
||||
case "wink3":
|
||||
id = "307"
|
||||
case "happy3":
|
||||
id = "308"
|
||||
case "excited3":
|
||||
id = "309"
|
||||
case "love3":
|
||||
id = "310"
|
||||
case "normal4":
|
||||
id = "401"
|
||||
case "surprise4":
|
||||
id = "402"
|
||||
case "serious4":
|
||||
id = "403"
|
||||
case "love4":
|
||||
id = "404"
|
||||
case "shine4":
|
||||
id = "405"
|
||||
case "sweat4":
|
||||
id = "406"
|
||||
case "shame4":
|
||||
id = "407"
|
||||
case "sleep4":
|
||||
id = "408"
|
||||
case "heart":
|
||||
id = "501"
|
||||
case "teardrop":
|
||||
id = "502"
|
||||
case "star":
|
||||
id = "503"
|
||||
}
|
||||
return fmt.Sprintf(`<img src="https://s.pximg.net/common/images/emoji/%s.png" alt="(%s)" class="emoji" />`, id, s)
|
||||
})
|
||||
return template.HTML(parsedString)
|
||||
})
|
||||
|
||||
engine.AddFunc("isEmpty", func(s string) bool {
|
||||
return len(s) < 1
|
||||
})
|
||||
|
||||
engine.AddFunc("isEmphasize", func(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
"R-18",
|
||||
"R-18G":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
// Randomly choose one and return
|
||||
return colors[rand.Intn(len(colors))]
|
||||
}
|
||||
|
||||
func GetTemplateFunctions() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"inc": func(n int) int {
|
||||
// For rankings to increment a number by 1
|
||||
return n + 1
|
||||
},
|
||||
"add": func(a int, b int) int {
|
||||
return a + b
|
||||
},
|
||||
|
||||
"dec": func(n int) int {
|
||||
return n - 1
|
||||
},
|
||||
|
||||
"toInt": func(s string) int {
|
||||
n, _ := strconv.Atoi(s)
|
||||
return n
|
||||
},
|
||||
|
||||
"proxyImage": func(url string) string {
|
||||
if strings.Contains(url, "s.pximg.net") {
|
||||
// This subdomain didn't get proxied
|
||||
return url
|
||||
}
|
||||
|
||||
regex := regexp.MustCompile(`.*?pximg\.net`)
|
||||
proxy := "https://" + configs.ProxyServer
|
||||
|
||||
return regex.ReplaceAllString(url, proxy)
|
||||
},
|
||||
"parseEmojis": func(s string) template.HTML {
|
||||
regex := regexp.MustCompile(`\(([^)]+)\)`)
|
||||
|
||||
parsedString := regex.ReplaceAllStringFunc(s, func(s string) string {
|
||||
s = s[1 : len(s)-1] // Get the string inside
|
||||
var id string
|
||||
|
||||
switch s {
|
||||
case "normal":
|
||||
id = "101"
|
||||
case "surprise":
|
||||
id = "102"
|
||||
case "serious":
|
||||
id = "103"
|
||||
case "heaven":
|
||||
id = "104"
|
||||
case "happy":
|
||||
id = "105"
|
||||
case "excited":
|
||||
id = "106"
|
||||
case "sing":
|
||||
id = "107"
|
||||
case "cry":
|
||||
id = "108"
|
||||
case "normal2":
|
||||
id = "201"
|
||||
case "shame2":
|
||||
id = "202"
|
||||
case "love2":
|
||||
id = "203"
|
||||
case "interesting2":
|
||||
id = "204"
|
||||
case "blush2":
|
||||
id = "205"
|
||||
case "fire2":
|
||||
id = "206"
|
||||
case "angry2":
|
||||
id = "207"
|
||||
case "shine2":
|
||||
id = "208"
|
||||
case "panic2":
|
||||
id = "209"
|
||||
case "normal3":
|
||||
id = "301"
|
||||
case "satisfaction3":
|
||||
id = "302"
|
||||
case "surprise3":
|
||||
id = "303"
|
||||
case "smile3":
|
||||
id = "304"
|
||||
case "shock3":
|
||||
id = "305"
|
||||
case "gaze3":
|
||||
id = "306"
|
||||
case "wink3":
|
||||
id = "307"
|
||||
case "happy3":
|
||||
id = "308"
|
||||
case "excited3":
|
||||
id = "309"
|
||||
case "love3":
|
||||
id = "310"
|
||||
case "normal4":
|
||||
id = "401"
|
||||
case "surprise4":
|
||||
id = "402"
|
||||
case "serious4":
|
||||
id = "403"
|
||||
case "love4":
|
||||
id = "404"
|
||||
case "shine4":
|
||||
id = "405"
|
||||
case "sweat4":
|
||||
id = "406"
|
||||
case "shame4":
|
||||
id = "407"
|
||||
case "sleep4":
|
||||
id = "408"
|
||||
case "heart":
|
||||
id = "501"
|
||||
case "teardrop":
|
||||
id = "502"
|
||||
case "star":
|
||||
id = "503"
|
||||
}
|
||||
return fmt.Sprintf(`<img src="https://s.pximg.net/common/images/emoji/%s.png" alt="(%s)" class="emoji" />`, id, s)
|
||||
})
|
||||
return template.HTML(parsedString)
|
||||
},
|
||||
|
||||
"randomColor": func() string {
|
||||
return GetRandomColor()
|
||||
},
|
||||
|
||||
"isEmpty": func(s string) bool {
|
||||
return len(s) < 1
|
||||
},
|
||||
|
||||
"isEmphasize": func(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
"R-18",
|
||||
"R-18G":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
2
main.go
2
main.go
|
@ -19,7 +19,7 @@ func setupRouter() *fiber.App {
|
|||
// HTML templates, automatically loaded
|
||||
engine := jet.New("./template", ".jet.html")
|
||||
|
||||
handler.GetTemplateFunctions(engine)
|
||||
engine.AddFuncMap(handler.GetTemplateFunctions())
|
||||
|
||||
server := fiber.New(fiber.Config{
|
||||
AppName: "PixivFE",
|
||||
|
|
|
@ -7,7 +7,7 @@ body {
|
|||
margin: 0;
|
||||
font-family: "Noto Sans CJK JP", "Open Sans", "Noto Sans", sans-serif;
|
||||
font-size: 1rem;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
background-color: #131516;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ body {
|
|||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
text-decoration: none;
|
||||
}
|
||||
.navbar .navbar-brand img {
|
||||
|
@ -59,10 +59,10 @@ body {
|
|||
padding: 7px 10px;
|
||||
margin: 0;
|
||||
border: none;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.navbar .search-bar .search-form-text::placeholder {
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.navbar .navbar-button {
|
||||
display: inline-block;
|
||||
|
@ -100,7 +100,7 @@ body {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
text-decoration: none;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
|
@ -393,12 +393,27 @@ body {
|
|||
|
||||
.tag-container {
|
||||
background-color: #262a2b;
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 40px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
margin-bottom: 4px;
|
||||
text-decoration: none;
|
||||
color: #d8d4cf;
|
||||
text-align: center;
|
||||
color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.tag-container .main {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.tag-container .sub {
|
||||
font-size: 0.7em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.switcher {
|
||||
|
@ -412,9 +427,9 @@ body {
|
|||
padding: 8px 5px;
|
||||
margin-top: 5px;
|
||||
background-color: #262a2b;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
text-decoration: none;
|
||||
text-decoration-color: #d8d4cf;
|
||||
text-decoration-color: #f5f5f5;
|
||||
}
|
||||
.switcher .switch-button:hover {
|
||||
background-color: rgba(38, 42, 43, 0.6);
|
||||
|
@ -434,7 +449,7 @@ body {
|
|||
.pagination .pagination-button {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.pagination .disabled {
|
||||
pointer-events: none;
|
||||
|
@ -448,7 +463,7 @@ body {
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
.footer a {
|
||||
color: #d8d4cf;
|
||||
color: #f5f5f5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
$bg: #131516;
|
||||
$fg: #d8d4cf;
|
||||
$fg: #f5f5f5;
|
||||
$bg-alt: #262a2b;
|
||||
$bg-alt-dimmed: #262a2b99;
|
||||
$blue: #3d7699;
|
||||
|
@ -461,12 +461,28 @@ body {
|
|||
|
||||
.tag-container {
|
||||
background-color: $bg-alt;
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 40px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
margin-bottom: 4px;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
color: $fg;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
border-radius: 4px;
|
||||
|
||||
.main {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.sub {
|
||||
font-size: 0.7em;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.switcher {
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
<div class="container">
|
||||
<div class="user-page">
|
||||
<div class="user-details">
|
||||
<img src="{{ proxyImage(User.Avatar) }}" alt="avatar" class="user-avatar" />
|
||||
<img
|
||||
src="{{ proxyImage(User.Avatar) }}"
|
||||
alt="avatar"
|
||||
class="user-avatar"
|
||||
/>
|
||||
<h2 class="user-name">{{ User.Name }}</h2>
|
||||
<p class="user-id">
|
||||
{{ User.Following }} Following | {{ User.MyPixiv }} MyPixiv
|
||||
|
@ -18,7 +22,17 @@
|
|||
</div>
|
||||
<div>
|
||||
{{ range User.FrequentTags }}
|
||||
<a class="tag-container" href="/tags/{{ .Name }}">#{{ .Name }}</a>
|
||||
<a href="/tags/{{ .Name }}">
|
||||
<div class="tag-container" style="background-color: {{ randomColor() }}">
|
||||
{{ if ! .TranslatedName }}
|
||||
<div class="main">{{ .Name }}</div>
|
||||
<div class="sub">#</div>
|
||||
{{ else }}
|
||||
<div class="main">{{ .TranslatedName }}</div>
|
||||
<div class="sub">#{{ .Name }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div>
|
||||
|
@ -31,7 +45,11 @@
|
|||
<a href="#" class="pagination-button disabled">Previous</a>
|
||||
{{ else }}
|
||||
<a href="/users/{{ User.ID }}?page=1" class="pagination-button">First</a>
|
||||
<a href="/users/{{ User.ID }}?page={{ dec(Page) }}" class="pagination-button">Previous</a>
|
||||
<a
|
||||
href="/users/{{ User.ID }}?page={{ dec(Page) }}"
|
||||
class="pagination-button"
|
||||
>Previous</a
|
||||
>
|
||||
{{ end }}
|
||||
|
||||
<a href="#" class="pagination-button disabled">{{ Page }}</a>
|
||||
|
@ -40,8 +58,16 @@
|
|||
<a href="#" class="pagination-button disabled">Next</a>
|
||||
<a href="#" class="pagination-button disabled">Last</a>
|
||||
{{ else }}
|
||||
<a href="/users/{{ User.ID }}?page={{ inc(Page) }}" class="pagination-button">Next</a>
|
||||
<a href="/users/{{ User.ID }}?page={{ dec(PageLimit) }}" class="pagination-button">Last</a>
|
||||
<a
|
||||
href="/users/{{ User.ID }}?page={{ inc(Page) }}"
|
||||
class="pagination-button"
|
||||
>Next</a
|
||||
>
|
||||
<a
|
||||
href="/users/{{ User.ID }}?page={{ dec(PageLimit) }}"
|
||||
class="pagination-button"
|
||||
>Last</a
|
||||
>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue