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
to the top of the answer - answerBodyHTML = fmt.Sprintf(` `, voteCount) + answerBodyHTML - } else { - // add to the top of the answer - answerBodyHTML = fmt.Sprintf(` `, 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 to the bottom of the answer - answerBodyHTML += fmt.Sprintf(` `, 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(`