diff --git a/internal/util/util.go b/internal/util/util.go index 1aa42e1..b006a8a 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -8,28 +8,37 @@ import ( func EnrichPost(body string) string { var b strings.Builder - for _, raw := range strings.Split(body, "\n") { - var out string - switch { - case strings.HasPrefix(raw, ">>"): - postId := strings.TrimPrefix(raw, ">>") - esc := template.HTMLEscapeString(raw) - out = fmt.Sprintf( - `%s`, - postId, esc, - ) - case strings.HasPrefix(raw, ">"): - esc := template.HTMLEscapeString(raw) - out = `` + esc + `` - default: - out = template.HTMLEscapeString(raw) + for _, rawLine := range strings.Split(body, "\n") { + var outLine string + + for i, rawWord := range strings.Split(rawLine, " ") { + var outWord string + if strings.HasPrefix(rawWord, ">>") { + postId := strings.TrimPrefix(rawWord, ">>") + esc := template.HTMLEscapeString(rawWord) + outWord = fmt.Sprintf( + `%s`, + postId, esc, + ) + } else { + outWord = template.HTMLEscapeString(rawWord) + } + + if i != 0 { + outLine += " " + } + outLine += outWord } - b.WriteString(out) - b.WriteString("
") + if strings.HasPrefix(rawLine, ">") && !strings.HasPrefix(rawLine, ">>") { + outLine = `` + outLine + `` + } + + b.WriteString(outLine) + b.WriteString("
") } return b.String() } diff --git a/web/static/index.css b/web/static/index.css index 75f84dd..e5e2bb6 100644 --- a/web/static/index.css +++ b/web/static/index.css @@ -146,12 +146,13 @@ body { .thread-subject { font-weight: bold; - color: #b294bb; + color: #0F0C5D; margin-right: 5px; } .post-op { margin-bottom: 10px; + font-size: 14px; } .post { @@ -159,8 +160,9 @@ body { margin: 5x; padding: 10px; background-color: #D6DAF0; - border: 1px solid #282a2e; + border: 1px solid #B7C5D9; margin-bottom: 10px; + font-size: 14px; } .post-highlighted { @@ -211,6 +213,17 @@ body { cursor: pointer; } +.reply-link-header { + color: rgb(52, 52, 92); + text-decoration: underline; + cursor: pointer; + margin-left: 8px; +} + +.reply-link-header:hover { + color: #D00; +} + /* GENERAL LAYOUT */ .container { diff --git a/web/static/thread.js b/web/static/thread.js new file mode 100644 index 0000000..7252f2a --- /dev/null +++ b/web/static/thread.js @@ -0,0 +1,34 @@ +const posts = Array.from(document.querySelectorAll("article")); + +const replies = {}; + +for (const post of posts) { + const postId = +post.id.split("-")[1]; + const postBody = post.querySelector("p").textContent; + + const replyLinkIds = [...postBody.matchAll(/(?:^|\s)>>(\d+)\b/g)].map(m => parseInt(m[1])); + for (const replyLinkId of replyLinkIds) { + replies[replyLinkId] = replies[replyLinkId] ? + replies[replyLinkId].add(postId) : + replies[replyLinkId] = new Set([postId]); + } +} + +for (const postId in replies) { + const post = $(`post-${postId}`); + const postRepliesContainer = post.querySelector(".post-replies"); + + const replyIds = Array.from(replies[postId]); + for (const replyId of replyIds) { + const replyLink = document.createElement("a"); + replyLink.textContent = `>>${replyId}`; + replyLink.classList.add("reply-link-header"); + replyLink.setAttribute("href", `#post-${replyId}`); + + replyLink.onmouseover = (e) => highlightPost(+replyId, e); + replyLink.onmouseleave = (e) => highlightPost(+replyId, e, false); + replyLink.onclick = onReplyLinkClick; + + postRepliesContainer.append(replyLink); + } +} diff --git a/web/views/shared/layout.templ b/web/views/shared/layout.templ index 2ac6698..017a08d 100644 --- a/web/views/shared/layout.templ +++ b/web/views/shared/layout.templ @@ -8,7 +8,7 @@ templ Layout() { Comfychan - + diff --git a/web/views/thread.templ b/web/views/thread.templ index b56d968..5585ab3 100644 --- a/web/views/thread.templ +++ b/web/views/thread.templ @@ -34,8 +34,9 @@ templ ThreadPost(post database.Post, thread *database.Thread) { _={ fmt.Sprintf("on click set #newPostBody.value to #newPostBody.value + '>>%d\n'", post.Id) } class=" post-num" > - No. { strconv.Itoa(post.Id) } + No.{ strconv.Itoa(post.Id) } +

@templ.Raw(util.EnrichPost(post.Body)) @@ -52,6 +53,7 @@ templ ThreadPosts(posts []database.Post) { templ Thread(board database.Board, thread database.Thread, posts []database.Post) { @shared.Layout() { + @BoardHeader(board)