`)
return htm.String()
}
type text struct {
TXT string
from int
to int
}
func tagval(t *html.Tokenizer) string {
for tt := t.Next(); ; {
switch tt {
default:
return ""
case html.TextToken:
return string(t.Text())
}
}
}
func ParseDescription(dscr devianter.Text) string {
var parseddescription strings.Builder
TagBuilder := func(tag string, content string) string {
if tag != "" {
var htm strings.Builder
htm.WriteString("<")
htm.WriteString(tag)
htm.WriteString(">")
htm.WriteString(content)
htm.WriteString("")
htm.WriteString(tag)
htm.WriteString(">")
return htm.String()
}
return content
}
if description, dl := dscr.Html.Markup, len(dscr.Html.Markup); dl != 0 &&
description[0] == '{' &&
description[dl-1] == '}' {
var descr struct {
Blocks []struct {
Text, Type string
InlineStyleRanges []struct {
Offset, Length int
Style string
}
EntityRanges []struct {
Offset, Length int
Key int
}
Data struct {
TextAlignment string
}
}
EntityMap map[string]struct {
Type string
Data struct {
Config struct {
Aligment string
Width int
}
Data devianter.Deviation
}
}
}
e := json.Unmarshal([]byte(description), &descr)
err(e)
entities := make(map[int]devianter.Deviation)
for n, x := range descr.EntityMap {
num, _ := strconv.Atoi(n)
entities[num] = x.Data.Data
}
for _, x := range descr.Blocks {
ranges := make(map[int]text)
if len(x.InlineStyleRanges) == 0 {
switch x.Type {
case "atomic":
d := entities[x.EntityRanges[0].Key]
parseddescription.WriteString(``)
case "unstyled":
parseddescription.WriteString(x.Text)
}
parseddescription.WriteString(" ")
}
for i, rngs := range x.InlineStyleRanges {
var tag string
switch rngs.Style {
case "BOLD":
tag = "b"
case "UNDERLINE":
tag = "u"
case "ITALIC":
tag = "i"
}
fromto := rngs.Offset + rngs.Length
ranges[i] = text{
TXT: TagBuilder(tag, x.Text[rngs.Offset:fromto]),
from: rngs.Offset,
to: fromto,
}
}
for _, r := range ranges {
var tag string
switch x.Type {
case "header-two":
tag = "h2"
case "unstyled":
tag = "p"
}
parseddescription.WriteString(r.TXT)
parseddescription.WriteString(TagBuilder(tag, x.Text[r.to:]))
}
}
} else if dl != 0 {
for tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)); ; {
t := tt.Next()
switch t {
case html.ErrorToken:
return parseddescription.String()
case html.StartTagToken, html.EndTagToken, html.SelfClosingTagToken:
token := tt.Token()
switch token.Data {
case "a":
for _, a := range token.Attr {
if a.Key == "href" {
url := strings.ReplaceAll(a.Val, "https://www.deviantart.com/users/outgoing?", "")
if strings.Contains(url, "deviantart") {
url = strings.ReplaceAll(url, "https://www.deviantart.com/", "")
url = strings.ReplaceAll(url, url[0:strings.Index(url, "/")+1], "")
}
parseddescription.WriteString("" + tagval(tt) + " ")
}
}
case "img":
var (
uri, title string
)
for b, a := range token.Attr {
switch a.Key {
case "src":
if len(a.Val) > 9 && a.Val[8:9] == "e" {
uri = UrlBuilder("media", "emojitar", a.Val[37:len(a.Val)-4], "?type=e")
}
case "title":
title = a.Val
}
if title != "" {
for x := -1; x < b; x++ {
parseddescription.WriteString("")
}
}
}
case "br", "li", "ul", "p", "b":
parseddescription.WriteString(token.String())
case "div":
parseddescription.WriteString("
")
}
case html.TextToken:
parseddescription.Write(tt.Text())
}
}
}
return parseddescription.String()
}
// навигация по страницам
type dlist struct {
Pages int
More bool
}
// FIXME: на некоротрых артах первая страница может вызывать полное отсутствие панели навигации.
func (s skunkyart) NavBase(c dlist) string {
// TODO: сделать понятнее
// навигация по страницам
var list strings.Builder
list.WriteString(" ")
p := s.Page
// функция для генерации ссылок
prevrev := func(msg string, page int, onpage bool) {
if !onpage {
list.WriteString(``)
list.WriteString(msg)
list.WriteString(" ")
} else {
list.WriteString(strconv.Itoa(page))
list.WriteString(" ")
}
}
// вперёд-назад
if p > 1 {
prevrev("<= Prev |", p-1, false)
} else {
p = 1
}
if c.Pages > 0 {
// назад
for x := p - 6; x < p && x > 0; x++ {
prevrev(strconv.Itoa(x), x, false)
}
// вперёд
for x := p; x <= p+6; x++ {
if x == p {
prevrev("", x, true)
x++
}
if x > p {
prevrev(strconv.Itoa(x), x, false)
}
}
}
// вперёд-назад
if p != 417 || c.More {
prevrev("| Next =>", p+1, false)
}
return list.String()
}
func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) string {
var list strings.Builder
if s.Atom && s.Page > 1 {
s.ReturnHTTPError(400)
return ""
} else if s.Atom {
list.WriteString(``)
list.WriteString(`SkunkyArt`)
// list.WriteString(``)
} else {
list.WriteString(`
`)
}
for _, data := range devs {
if !(data.NSFW && !CFG.Nsfw) {
url := ParseMedia(data.Media)
if s.Atom {
id := strconv.Itoa(data.ID)
list.WriteString(``)
list.WriteString(data.Author.Username)
list.WriteString(``)
list.WriteString(data.Title)
list.WriteString(``)
list.WriteString(id)
list.WriteString(``)
list.WriteString(data.PublishedTime.UTC().Format("Mon, 02 Jan 2006 15:04:05 -0700"))
list.WriteString(``)
list.WriteString(``)
list.WriteString(data.Title)
list.WriteString(`