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