Commit e07e1a25b2

e07e1a25b26d3fd2b8fd097491d055fe7b002d2b

parent: 99fe9cf964

Unsigned

lost+skunk <skunky@ebloid.ru> · 2024-07-08 16:01 UTC

небольшие улучшения парсинга описания/комментариев

Layout: unified · split

app/util.go +106 −6
@@ -14,6 +14,7 @@ import (
1414 "time"
1515
1616 "git.macaw.me/skunky/devianter"
17 "golang.org/x/net/html"
1718)
1819
1920// парсинг темплейтов
@@ -95,18 +96,59 @@ func ParseDescription(dscr devianter.Text) string {
9596 description[dl-1] == '}' {
9697 var descr struct {
9798 Blocks []struct {
98 Key, Text, Type string
99 Text, Type string
99100 InlineStyleRanges []struct {
100101 Offset, Length int
101102 Style string
102103 }
104 EntityRanges []struct {
105 Offset, Length int
106 Key int
107 }
108 Data struct {
109 TextAlignment string
110 }
111 }
112 EntityMap map[string]struct {
113 Type string
114 Data struct {
115 Config struct {
116 Aligment string
117 Width int
118 }
119 Data devianter.Deviation
120 }
103121 }
104122 }
105123 e := json.Unmarshal([]byte(description), &descr)
106124 err(e)
107125
126 entities := make(map[int]devianter.Deviation)
127 for n, x := range descr.EntityMap {
128 num, _ := strconv.Atoi(n)
129 entities[num] = x.Data.Data
130 }
131
108132 for _, x := range descr.Blocks {
109133 ranges := make(map[int]text)
134
135 if len(x.InlineStyleRanges) == 0 {
136 switch x.Type {
137 case "atomic":
138 d := entities[x.EntityRanges[0].Key]
139 parseddescription.WriteString(`<img width="50%" src="`)
140 parseddescription.WriteString(ParseMedia(d.Media))
141 parseddescription.WriteString(`" title="`)
142 parseddescription.WriteString(d.Author.Username)
143 parseddescription.WriteString(" - ")
144 parseddescription.WriteString(d.Title)
145 parseddescription.WriteString(`">`)
146 case "unstyled":
147 parseddescription.WriteString(x.Text)
148 }
149 parseddescription.WriteString("<br>")
150 }
151
110152 for i, rngs := range x.InlineStyleRanges {
111153 var tag string
112154
@@ -140,7 +182,66 @@ func ParseDescription(dscr devianter.Text) string {
140182 }
141183 }
142184 } else if dl != 0 {
143 parseddescription.WriteString(description)
185 tagval := func(t *html.Tokenizer) string {
186 for {
187 tt := t.Next()
188 switch tt {
189 case html.ErrorToken:
190 return ""
191 case html.TextToken:
192 return string(t.Text())
193 }
194 }
195 }
196
197 tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup))
198 for {
199 t := tt.Next()
200 switch t {
201 case html.ErrorToken:
202 return parseddescription.String()
203 case html.StartTagToken, html.EndTagToken, html.SelfClosingTagToken:
204 token := tt.Token()
205 switch token.Data {
206 case "a":
207 for _, a := range token.Attr {
208 if a.Key == "href" {
209 url := strings.ReplaceAll(a.Val, "https://www.deviantart.com/users/outgoing?", "")
210 if strings.Contains(url, "deviantart") {
211 url = strings.ReplaceAll(url, "https://www.deviantart.com/", "")
212 url = strings.ReplaceAll(url, url[0:strings.Index(url, "/")+1], "")
213 }
214 parseddescription.WriteString("<a target=\"_blank\" href=\"" + url + "\">" + tagval(tt) + "</a> ")
215 }
216 }
217 case "img":
218 var (
219 uri, title string
220 )
221 for b, a := range token.Attr {
222 switch a.Key {
223 case "src":
224 if len(a.Val) > 9 && a.Val[8:9] == "e" {
225 uri = UrlBuilder("media", "emojitar", a.Val[37:len(a.Val)-4], "?type=e")
226 }
227 case "title":
228 title = a.Val
229 }
230 if title != "" {
231 for x := -1; x < b; x++ {
232 parseddescription.WriteString("<img src=\"" + uri + "\" title=\"" + title + "\">")
233 }
234 }
235 }
236 case "br", "li", "ul", "p", "b":
237 parseddescription.WriteString(token.String())
238 case "div":
239 parseddescription.WriteString("<p> ")
240 }
241 case html.TextToken:
242 parseddescription.Write(tt.Text())
243 }
244 }
144245 }
145246
146247 return parseddescription.String()
@@ -234,7 +335,7 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
234335 }
235336 for _, data := range devs {
236337 if !(data.NSFW && !CFG.Nsfw) {
237 url := s.ParseMedia(data.Media)
338 url := ParseMedia(data.Media)
238339 if s.Atom {
239340 id := strconv.Itoa(data.ID)
240341 list.WriteString(`<entry><author><name>`)
@@ -307,7 +408,6 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
307408 return list.String()
308409}
309410
310// FIXME: первый комментарий не отображается.
311411func (s skunkyart) ParseComments(c devianter.Comments) string {
312412 var cmmts strings.Builder
313413 replied := make(map[int]string)
@@ -354,7 +454,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string {
354454 cmmts.WriteString(x.Posted.UTC().String())
355455 cmmts.WriteString("]<p>")
356456
357 cmmts.WriteString(x.Comment)
457 cmmts.WriteString(ParseDescription(x.TextContent))
358458 cmmts.WriteString("<p>👍: ")
359459 cmmts.WriteString(strconv.Itoa(x.Likes))
360460 cmmts.WriteString(" ⏩: ")
@@ -369,7 +469,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string {
369469 return cmmts.String()
370470}
371471
372func (s skunkyart) ParseMedia(media devianter.Media) string {
472func ParseMedia(media devianter.Media) string {
373473 url := devianter.UrlFromMedia(media)
374474 if len(url) != 0 {
375475 url = url[21:]
app/wrapper.go +8 −4
@@ -127,7 +127,7 @@ func (s skunkyart) GRUser() {
127127 case "cover_deviation":
128128 group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
129129 group.About.BGMeta.Url = s.ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url)
130 group.About.BG = s.ParseMedia(group.About.BGMeta.Media)
130 group.About.BG = ParseMedia(group.About.BGMeta.Media)
131131 case "group_admins":
132132 var htm strings.Builder
133133 for _, z := range x.ModuleData.GroupAdmins.Results {
@@ -165,7 +165,7 @@ func (s skunkyart) GRUser() {
165165 folders.WriteString(`<a href="`)
166166 folders.WriteString(s.ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
167167 folders.WriteString(`"><img loading="lazy" src="`)
168 folders.WriteString(s.ParseMedia(x.Thumb.Media))
168 folders.WriteString(ParseMedia(x.Thumb.Media))
169169 folders.WriteString(`" title="`)
170170 folders.WriteString(x.Thumb.Title)
171171 folders.WriteString(`"></a><br>`)
@@ -212,10 +212,14 @@ func (s skunkyart) Deviation(author, postname string) {
212212 id := id_search[len(id_search)-1]
213213 post.Post = devianter.DeviationFunc(id, author)
214214
215 post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
215 if post.Post.Deviation.TextContent.Excerpt != "" {
216 post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
217 } else {
218 post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText)
219 }
216220 // время публикации
217221 post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
218 post.Post.IMG = s.ParseMedia(post.Post.Deviation.Media)
222 post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
219223 for _, x := range post.Post.Deviation.Extended.RelatedContent {
220224 if len(x.Deviations) != 0 {
221225 post.Related = s.DeviationList(x.Deviations)
css/skunky.css +28
@@ -60,6 +60,7 @@ form input, button, select {
6060 color: rgb(160, 0, 147);
6161}
6262.content {
63 align-items: center;
6364 border-radius: 3px;
6465 display: flex;
6566 flex-wrap: wrap;
@@ -112,4 +113,31 @@ form input, button, select {
112113 word-break: break-all;
113114 text-align: center;
114115 width: 5%;
116}
117
118@media screen and (orientation: portrait) {
119 header {
120 scale: 155%;
121 justify-content: center;
122 }
123 .content {
124 margin: auto;
125 display: inherit;
126 scale: 100%;
127 }
128 .block {
129 max-width: 60%;
130 }
131}
132
133@media screen and (max-width: 1462px) {
134 .block {
135 max-width: 30%;
136 }
137}
138
139@media screen and (min-width: 788px) and (max-width: 884px) {
140 .block {
141 max-width: 35%;
142 }
115143}
\ No newline at end of file
go.mod +4 −1
@@ -4,4 +4,7 @@ go 1.22.3
44
55replace git.macaw.me/skunky/devianter v0.1.0 => /home/skunk/projects/devianter
66
7require git.macaw.me/skunky/devianter v0.1.0
7require (
8 git.macaw.me/skunky/devianter v0.1.0
9 golang.org/x/net v0.27.0
10)
go.sum +2
@@ -0,0 +1,2 @@
1golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
2golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
instances.json added +14
@@ -0,0 +1,14 @@
1{
2 "instances": [{
3 "urls": [{
4 "i2p": "http://skunky.i2p/art",
5 "tor": "http://skunky0wjkf8j8ajofgh98aOZjhu8f.onion/art",
6 "ygg": "http://[324:71e:281a:9ed3::fa11]/skunkyart",
7 "clearnet": "https://skunky.net/art"
8 }],
9 "settings": {
10 "nsfw": true,
11 "proxy": true
12 }
13 }]
14}
\ No newline at end of file