diff --git a/public/question.css b/public/question.css index 12327b9..adee934 100644 --- a/public/question.css +++ b/public/question.css @@ -102,6 +102,10 @@ img { height: 2rem; } +.comments { + margin-top: 1rem; +} + .comments-parent { display: flex; flex-direction: column; diff --git a/src/routes/question.go b/src/routes/question.go index 1104c7a..de14ca5 100644 --- a/src/routes/question.go +++ b/src/routes/question.go @@ -9,6 +9,8 @@ import ( "regexp" "strings" + "anonymousoverflow/src/types" + "github.com/PuerkitoBio/goquery" "github.com/gin-gonic/gin" "github.com/go-resty/resty/v2" @@ -39,10 +41,14 @@ func ViewQuestion(c *gin.Context) { panic(err) } + newFilteredQuestion := types.FilteredQuestion{} + questionTextParent := doc.Find("h1.fs-headline1") questionText := questionTextParent.Children().First().Text() + newFilteredQuestion.Title = questionText + questionPostLayout := doc.Find("div.post-layout").First() questionBodyParent := doc.Find("div.s-prose") @@ -52,7 +58,22 @@ func ViewQuestion(c *gin.Context) { panic(err) } - questionBodyParentHTML = utils.FindAndReturnComments(questionBodyParentHTML, questionPostLayout) + newFilteredQuestion.Body = template.HTML(questionBodyParentHTML) + + questionBodyText := questionBodyParent.Text() + + // remove all whitespace to create the shortened body desc + shortenedBody := strings.TrimSpace(questionBodyText) + + // remove all newlines + shortenedBody = strings.ReplaceAll(shortenedBody, "\n", " ") + + // get the first 50 chars + shortenedBody = shortenedBody[:50] + + newFilteredQuestion.ShortenedBody = shortenedBody + + comments := utils.FindAndReturnComments(questionBodyParentHTML, questionPostLayout) // parse any code blocks and highlight them answerCodeBlocks := questionCodeBlockRegex.FindAllString(questionBodyParentHTML, -1) @@ -87,6 +108,8 @@ func ViewQuestion(c *gin.Context) { } }) + newFilteredQuestion.Timestamp = questionTimestamp + userDetails := questionMetadata.Find("div.user-details") questionAuthor := "" @@ -111,9 +134,14 @@ func ViewQuestion(c *gin.Context) { } }) - answers := []template.HTML{} + newFilteredQuestion.AuthorName = questionAuthor + newFilteredQuestion.AuthorURL = questionAuthorURL + + answers := []types.FilteredAnswer{} doc.Find("div.answer").Each(func(i int, s *goquery.Selection) { + newFilteredAnswer := types.FilteredAnswer{} + postLayout := s.Find("div.post-layout") voteCell := postLayout.Find("div.votecell") answerCell := postLayout.Find("div.answercell") @@ -122,13 +150,8 @@ func ViewQuestion(c *gin.Context) { voteCount := html.EscapeString(voteCell.Find("div.js-vote-count").Text()) - if s.HasClass("accepted-answer") { - // add
Accepted Answer
to the top of the answer - answerBodyHTML = fmt.Sprintf(`
Accepted Answer - %s Upvotes
`, voteCount) + answerBodyHTML - } else { - // add
%s Upvotes
to the top of the answer - answerBodyHTML = fmt.Sprintf(`
%s Upvotes
`, voteCount) + answerBodyHTML - } + newFilteredAnswer.Upvotes = voteCount + newFilteredAnswer.IsAccepted = s.HasClass("accepted-answer") answerFooter := s.Find("div.mt24") @@ -156,8 +179,9 @@ func ViewQuestion(c *gin.Context) { answerTimestamp = html.EscapeString(s.Find("span.relativetime").Text()) }) - // append
Answered %s by %s
to the bottom of the answer - answerBodyHTML += fmt.Sprintf(`
Answered %s by %s
`, answerTimestamp, answerAuthorURL, answerAuthorName) + newFilteredAnswer.AuthorName = answerAuthorName + newFilteredAnswer.AuthorURL = answerAuthorURL + newFilteredAnswer.Timestamp = answerTimestamp // parse any code blocks and highlight them answerCodeBlocks := codeBlockRegex.FindAllString(answerBodyHTML, -1) @@ -171,9 +195,12 @@ func ViewQuestion(c *gin.Context) { answerBodyHTML = strings.Replace(answerBodyHTML, codeBlock, highlightedCodeBlock, 1) } - answerBodyHTML = utils.FindAndReturnComments(answerBodyHTML, postLayout) + comments = utils.FindAndReturnComments(answerBodyHTML, postLayout) - answers = append(answers, template.HTML(answerBodyHTML)) + newFilteredAnswer.Comments = comments + newFilteredAnswer.Body = template.HTML(answerBodyHTML) + + answers = append(answers, newFilteredAnswer) }) imagePolicy := "'self' https:" @@ -183,16 +210,11 @@ func ViewQuestion(c *gin.Context) { } c.HTML(200, "question.html", gin.H{ - "title": questionText, - "body": template.HTML(questionBodyParentHTML), - "timestamp": questionTimestamp, - "author": questionAuthor, - "authorURL": questionAuthorURL, - "answers": answers, - "imagePolicy": imagePolicy, - "shortenedBody": questionBodyParent.Text()[0:50], - "theme": c.MustGet("theme").(string), - "currentUrl": fmt.Sprintf("%s/questions/%s/%s", os.Getenv("APP_URL"), questionId, questionTitle), + "question": newFilteredQuestion, + "answers": answers, + "imagePolicy": imagePolicy, + "theme": c.MustGet("theme").(string), + "currentUrl": fmt.Sprintf("%s/questions/%s/%s", os.Getenv("APP_URL"), questionId, questionTitle), }) } diff --git a/src/types/answer.go b/src/types/answer.go new file mode 100644 index 0000000..40ec193 --- /dev/null +++ b/src/types/answer.go @@ -0,0 +1,17 @@ +package types + +import "html/template" + +type FilteredAnswer struct { + Upvotes string + IsAccepted bool + + AuthorName string + AuthorURL string + + Timestamp string + + Body template.HTML + + Comments []FilteredComment +} diff --git a/src/types/comment.go b/src/types/comment.go new file mode 100644 index 0000000..950105e --- /dev/null +++ b/src/types/comment.go @@ -0,0 +1,8 @@ +package types + +type FilteredComment struct { + Text string + Timestamp string + AuthorName string + AuthorURL string +} diff --git a/src/types/question.go b/src/types/question.go new file mode 100644 index 0000000..1aeba70 --- /dev/null +++ b/src/types/question.go @@ -0,0 +1,12 @@ +package types + +import "html/template" + +type FilteredQuestion struct { + Title string + Body template.HTML + Timestamp string + AuthorName string + AuthorURL string + ShortenedBody string +} diff --git a/src/utils/comments.go b/src/utils/comments.go index 4317834..fbade7e 100644 --- a/src/utils/comments.go +++ b/src/utils/comments.go @@ -1,17 +1,12 @@ package utils import ( - "fmt" - "html" - "strings" + "anonymousoverflow/src/types" "github.com/PuerkitoBio/goquery" ) -func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (outHtml string) { - outHtml = inHtml - - comments := []string{} +func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (comments []types.FilteredComment) { commentsComponent := postLayout.Find("div.js-post-comments-component") @@ -39,21 +34,22 @@ func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (outHtm return } - commentAuthorURL = html.EscapeString(commentAuthor.AttrOr("href", "")) + commentAuthorURL = commentAuthor.AttrOr("href", "") } - commentTimestamp := html.EscapeString(commentBody.Find("span.relativetime-clean").Text()) + commentTimestamp := commentBody.Find("span.relativetime-clean").Text() - comment := fmt.Sprintf(`
%s
Commented %s by %s.
`, commentCopy, commentTimestamp, commentAuthorURL, html.EscapeString(commentAuthor.Text())) + newFilteredComment := types.FilteredComment{ + Text: commentCopy, + Timestamp: commentTimestamp, + AuthorName: commentAuthor.Text(), + AuthorURL: commentAuthorURL, + } - comments = append(comments, comment) + comments = append(comments, newFilteredComment) }) - if len(comments) > 0 { - outHtml = inHtml + fmt.Sprintf(`
Show %d comments
%s
`, len(comments), strings.Join(comments, "")) - } - return } diff --git a/templates/question.html b/templates/question.html index 3e1ca93..c10896c 100644 --- a/templates/question.html +++ b/templates/question.html @@ -1,7 +1,7 @@ - {{ .title }} + {{ .question.Title }} @@ -13,7 +13,7 @@ - +
@@ -34,23 +34,69 @@
-

{{ .title }}

+

{{ .question.Title }}

- Asked {{ .timestamp }} by + Asked {{ .question.Timestamp }} by {{ .author }}{{ .question.AuthorName }}.

-
{{ .body }}
+
{{ .question.Body }}

Answers

{{ range $answer := .answers }} -
{{ $answer }}
+
+
+ {{ if $answer.IsAccepted }} Accepted - {{ end }} + {{$answer.Upvotes}} Votes +
+ {{ $answer.Body }} +
+
+ Answered {{ $answer.Timestamp }} by + {{ $answer.AuthorName }} +
+
+ {{ if $answer.Comments }} +
+ + Show {{ (len $answer.Comments) }} comments + +
+ {{ range $comment := $answer.Comments }} +
+
+
+ {{ $comment.Text }} +
+
+ Commented {{ $comment.Timestamp }} by + {{ $comment.AuthorName }}. +
+
+
+ {{end}} +
+
+ {{end}} +

{{ end }}