mirror of
https://github.com/httpjamesm/AnonymousOverflow.git
synced 2024-12-06 19:16:43 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fa89879cf | |||
| cc9e549aaf | |||
| 6bfed5a9e3 | |||
| a0df61a92d | |||
| bbf098e7f4 | |||
| 2c4ded0800 | |||
| f0e42287cf | |||
| 9ebb6c90d9 | |||
| 69d96d646d | |||
| c87ce26da8 | |||
| 3dea27b09f | |||
| 2b608b4725 |
@@ -22,6 +22,9 @@ This project is super lightweight by design. The UI is simple and the frontend i
|
||||
| [overflow.smnz.de](https://overflow.smnz.de) | Germany | Operated by [smnz.de](https://smnz.de) |
|
||||
| [anonymousoverflow.esmailelbob.xyz](https://anonymousoverflow.esmailelbob.xyz/) | Canada | Operated by [Esmail EL BoB](https://esmailelbob.xyz) |
|
||||
| [overflow.lunar.icu](https://overflow.lunar.icu) | Germany | Operated by [lunar.icu](https://lunar.icu/) |
|
||||
| [overflow.adminforge.de](https://overflow.adminforge.de/) | Germany | Operated by [adminForge](https://adminforge.de/) |
|
||||
| [ao.foss.wtf](https://ao.foss.wtf) | Germany | Operated by [foss.wtf](https://foss.wtf) |
|
||||
| [overflow.hostux.net](https://overflow.hostux.net/) | France | Operated by [Hostux](https://hostux.net/) |
|
||||
|
||||
## Other Instances
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package config
|
||||
|
||||
var Version = "1.5.1"
|
||||
var Version = "1.6"
|
||||
|
||||
@@ -48,10 +48,17 @@ func main() {
|
||||
r.GET("/options/:name", routes.ChangeOptions)
|
||||
|
||||
r.GET("/", routes.GetHome)
|
||||
|
||||
r.POST("/", routes.PostHome)
|
||||
|
||||
r.GET("/questions/:id", func(c *gin.Context) {
|
||||
// redirect user to the question with the title
|
||||
c.Redirect(302, fmt.Sprintf("/questions/%s/placeholder", c.Param("id")))
|
||||
})
|
||||
r.GET("/questions/:id/:title", routes.ViewQuestion)
|
||||
r.GET("/questions/:id/:title/:answerId", func(c *gin.Context) {
|
||||
// redirect user to the answer with the title
|
||||
c.Redirect(302, fmt.Sprintf("/questions/%s/%s#%s", c.Param("id"), c.Param("title"), c.Param("answerId")))
|
||||
})
|
||||
|
||||
r.GET("/proxy", routes.GetImage)
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 363 B |
+33
-9
@@ -29,6 +29,20 @@ body {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-tags {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.card-tags .tag {
|
||||
background-color: var(--meta-bg);
|
||||
color: var(--tag-text-color);
|
||||
padding: 0.5rem;
|
||||
border-radius: 5px;
|
||||
font-size: 0.8rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: var(--code-bg);
|
||||
padding: 0.15rem;
|
||||
@@ -50,22 +64,25 @@ pre {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.post-divider,
|
||||
.answer-divider {
|
||||
.post-divider {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.answer-divider {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background-color: var(--divider-color);
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.answer {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 1px solid var(--muted-text-color);
|
||||
}
|
||||
|
||||
.answer:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.answer-meta {
|
||||
border-radius: 5px;
|
||||
padding: 1rem;
|
||||
@@ -73,6 +90,13 @@ img {
|
||||
margin-bottom: 1rem;
|
||||
background-color: var(--meta-bg);
|
||||
color: var(--text-color);
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.answer-meta p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.answer-meta.accepted {
|
||||
@@ -120,7 +144,7 @@ img {
|
||||
.answers-header .sorting form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.answers-header select {
|
||||
|
||||
@@ -98,6 +98,9 @@ func ViewQuestion(c *gin.Context) {
|
||||
|
||||
questionPostLayout := doc.Find("div.post-layout").First()
|
||||
|
||||
questionTags := utils.GetPostTags(questionPostLayout)
|
||||
newFilteredQuestion.Tags = questionTags
|
||||
|
||||
questionBodyParent := doc.Find("div.s-prose")
|
||||
|
||||
questionBodyParentHTML, err := questionBodyParent.Html()
|
||||
@@ -193,6 +196,7 @@ func ViewQuestion(c *gin.Context) {
|
||||
answers := []types.FilteredAnswer{}
|
||||
|
||||
doc.Find("div.answer").Each(func(i int, s *goquery.Selection) {
|
||||
|
||||
newFilteredAnswer := types.FilteredAnswer{}
|
||||
|
||||
postLayout := s.Find("div.post-layout")
|
||||
@@ -232,6 +236,9 @@ func ViewQuestion(c *gin.Context) {
|
||||
answerTimestamp = html.EscapeString(s.Find("span.relativetime").Text())
|
||||
})
|
||||
|
||||
answerId, _ := s.Attr("data-answerid")
|
||||
newFilteredAnswer.ID = answerId
|
||||
|
||||
newFilteredAnswer.AuthorName = answerAuthorName
|
||||
newFilteredAnswer.AuthorURL = answerAuthorURL
|
||||
newFilteredAnswer.Timestamp = answerTimestamp
|
||||
|
||||
@@ -3,6 +3,8 @@ package types
|
||||
import "html/template"
|
||||
|
||||
type FilteredAnswer struct {
|
||||
ID string
|
||||
|
||||
Upvotes string
|
||||
IsAccepted bool
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@ type FilteredQuestion struct {
|
||||
AuthorURL string
|
||||
ShortenedBody string
|
||||
Comments []FilteredComment
|
||||
Tags []string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
func GetPostTags(postLayout *goquery.Selection) []string {
|
||||
var tags []string
|
||||
postLayout.Find("a.post-tag").Each(func(i int, s *goquery.Selection) {
|
||||
tags = append(tags, s.Text())
|
||||
})
|
||||
return tags
|
||||
}
|
||||
+16
-5
@@ -38,6 +38,11 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">{{ .question.Body }}</div>
|
||||
<div class="card-tags">
|
||||
{{ range .question.Tags }}
|
||||
<div class="tag">{{ . }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ if .question.Comments }} {{ template "comments.html"
|
||||
.question }} {{end}}
|
||||
</div>
|
||||
@@ -50,8 +55,8 @@
|
||||
<option disabled value="">Sort answers by...</option>
|
||||
<option value="votes"{{ if eq .sortValue "votes" }} selected{{ end }}>Votes</option>
|
||||
<option value="trending"{{ if eq .sortValue "trending" }} selected{{ end }}>Trending</option>
|
||||
<option value="newest"{{ if eq .sortValue "newest" }} selected{{ end }}>Newest</option>
|
||||
<option value="oldest"{{ if eq .sortValue "oldest" }} selected{{ end }}>Oldest</option>
|
||||
<option value="newest"{{ if eq .sortValue "newest" }} selected{{ end }}>Date modified (newest first)</option>
|
||||
<option value="oldest"{{ if eq .sortValue "oldest" }} selected{{ end }}>Date created (oldest first)</option>
|
||||
</select>
|
||||
<button type="submit">
|
||||
<img
|
||||
@@ -63,13 +68,20 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ range $answer := .answers }}
|
||||
<div class="answer">
|
||||
<div class="answer" id="{{ $answer.ID }}">
|
||||
<div
|
||||
class="answer-meta{{ if $answer.IsAccepted }} accepted{{end}}"
|
||||
>
|
||||
<p>
|
||||
{{ if $answer.IsAccepted }} Accepted - {{ end }}
|
||||
{{$answer.Upvotes}} Votes
|
||||
</div>
|
||||
</p>
|
||||
<a href="#{{ $answer.ID }}" class="answer-link">
|
||||
<div class="icon">
|
||||
<img src="/static/icons/link.svg" alt="Paperclip icon" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{{ $answer.Body }}
|
||||
<div class="answer-author-parent">
|
||||
<div class="answer-author">
|
||||
@@ -85,7 +97,6 @@
|
||||
{{ if $answer.Comments }} {{ template "comments.html" $answer }}
|
||||
{{end}}
|
||||
</div>
|
||||
<hr class="answer-divider" />
|
||||
{{ end }}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user