beautifulhugo icon indicating copy to clipboard operation
beautifulhugo copied to clipboard

[Feature] Staticman Comment Reply

Open VincentTam opened this issue 6 years ago • 7 comments

Demo site

https://vincenttam.gitlab.io/bhdemo

screenshot_2018-11-16 my second post 2

New features

  • comment reply
  • comment preview

Bug fixes and modifications

  • #221
  • dancwilliams/networkhobo#373
  • added standard LaTeX math delimiters $...$ to KaTeX's default delimiters.

Backward compatibility

I tested this for another existing Beautiful Hugo site. Despite some missing fields (c.f. staticman.yml) in existing YML comment data, this works fine.

old sites using this PR

Quick guide to test this pull request

If you're using a theme as a Git submodule (as recommended in Hugo's official tutorial), you may create a new (local/GitLab/etc) (private) repo for this theme and run these commands to get this PR merged against a testing branch pr222 in the private repo. I denote the URL of this repo as the upstream.

$ git remote -v
upstream	https://github.com/halogenica/beautifulhugo.git (fetch)
upstream	https://github.com/halogenica/beautifulhugo.git (push)
... # other remote omitted
$ git checkout -b pr222 # test on a new branch pr222
$ git fetch upstream pull/222/head # git pull will be rejected
$ git merge FETCH_HEAD # manually merge the this PR against branch pr222
$ cd <your-blog>
... # edit your .gitmodules with url="<repo-containing-pr222>" and branch = "pr222"
$ git submodule sync # inform Git the changes in .gitmodules
$ git submodule update --remote --recursive # switch to the HEAD of your cloned repo for the theme

Remarks rooms for improvement

I'm not a developer. I wrote this based on my basic knowledge in web markup and scripting languages, @dancwilliams's great example, some Google search results and trial-and-error. This commit history is far from clean: I've changed some important field names and file structure a few times.

  • I don't wish to change the <article id="comment-1"> in layouts/partials/staticman-comments.html, so I store the comment _id in a "reply to XYZ" link button.
  • Reply comments have id="comment-1r1". Though I call them "nested comments", a reply comment is not an HTML children() of any .static-comment.
  • I've changed {{ if not .parent }} in layouts/partials/staticman-comments.html (introduced at d68cf2e04dd2d64efa0c8e6312aa271402fb06c0 by @badele) to {{ if not .replyThread }} because options[parent] is for subscription entries. It's clear (to me, at least) that @badele intends to loop over all "main comment" (as in eduardoboucas/staticman#35) first.
    • I've chosen replyThread instead of threadID because a "main comment" starts a thread, so it belongs to a thread, thus it would look a bit strange without a threadID.
    • For each reply comment, there's (1) main comment, and (2) reply target, which aren't identical in general. Provided the double-loop structure discussed in eduardoboucas/staticman#35 and implemented at d68cf2e04dd2d64efa0c8e6312aa271402fb06c0, whose outer loop iterates through (1) main comment and inner loop iterates through the reply recomment, there's two possible ways to reconstruct the whole reply tree, and this PR inclines to the Staticman side more than the Hugo side.
  • CSS can be improved, but the logic is already there.
  • I've introduced an offset in static/js/staticman.js so that the anchor target won't get covered by the navbar. Maybe there's a pure CSS solution.
  • I kept @dancwilliams's choice of using <a> instead of <button> for reply button. After hours of trial-and-error, I've to introduce either a delay or an animation (the way I prefered) so that I can jump to a different element (the top of the post) by feeding another href (id of the "reply to" button)
  • Internationization of "reply to" in the link button is missing.

See also

  • Pre-release notes: https://github.com/VincentTam/beautifulhugo/releases/tag/reply-rc1.9
  • My dedicated blog post: https://vincenttam.gitlab.io/post/2018-11-17-nested-comments-in-beautiful-hugo/

VincentTam avatar Nov 16 '18 12:11 VincentTam

Update: Towards a more static nested comments support

Before fe547af, the anchor in each comment reply is too complicated. It finds the id attribute of the reply button in the reply target (stored as targetPostID) from href in the anchor a.comment-reply-target. Then targetPostID is used to find the true target id in the form #comment-xry. Finally, the behaviour of the onRelease event of the anchor is tweaked with animate in the JavaScript so that it would smoothly scroll to the true target.

https://github.com/halogenica/beautifulhugo/blob/8f3b0c3296ebb04fdb76b95d7af23787657d8ea8/static/js/staticman.js#L57-L61

Get the whole picture from two separate files are hard, so as the difficulty to maintaint them. The recent commits attempt to directly compute the right anchor links by Hugo (as a staticman site generaor). i.e. The anchor a.comment-reply-target now gives href like comment-1r1, so that there's no need to use the reply button as an intermediate.

The new way makes use of Hugo's .Scratch with maps. Each post ID is used as a mey to maps to an integer representing the order of the post in a thread. Each main post (those without parents) are assigned 0. The first comment reply in a thread is assigned 1, and so on... The line {{ $.Scratch.Delete "replyIndices" }} is optional. This PR works fine without resetting the Scratch mapping because the ID for posts are unique.

diff --git a/layouts/partials/staticman-comments.html b/layouts/partials/staticman-comments.html
index e3c21dd..9d8a0a4 100644
--- a/layouts/partials/staticman-comments.html
+++ b/layouts/partials/staticman-comments.html
@@ -20,6 +20,7 @@
         {{ $.Scratch.Add "hasComments" 1 }}
         {{ $.Scratch.Set "hasReplies" 0 }}
         {{ $.Scratch.Set "threadID" ._id }}
+        {{ $.Scratch.SetInMap "replyIndices" ._id 0 }}
         <article id="comment-{{ $.Scratch.Get "hasComments" }}" class="static-comment">
           <img class="comment-avatar" src="https://www.gravatar.com/avatar/{{ .email }}?s=48">
           {{ if .website }}
@@ -37,6 +38,7 @@
         {{ range $comments }}
           {{ if eq .replyThread ($.Scratch.Get "threadID") }}
             {{ $.Scratch.Add "hasReplies" 1 }}
+            {{ $.Scratch.SetInMap "replyIndices" ._id ($.Scratch.Get "hasReplies") }}
             <article id="comment-{{ $.Scratch.Get "hasComments" }}r{{ $.Scratch.Get "hasReplies" }}" class="static-comment static-comment-reply">
               <img class="comment-avatar" src="https://www.gravatar.com/avatar/{{ .email }}?s=48">
               {{ if .website }}
@@ -44,7 +46,9 @@
               {{ else }}
               <h4 class="comment-author">{{ .name }}</h4>
               {{ end }}
-              <h5 class="comment-reply-target"><a href="#{{ .replyID }}"><i class="fas fa-reply"></i> {{ .replyName }}</a></h5>
+              {{- $replyTargetIndex := (index ($.Scratch.Get "replyIndices") .replyID) -}}
+              {{- $replyLinkEnd := cond (eq $replyTargetIndex 0) "" (print "r" $replyTargetIndex) -}}
+              <h5 class="comment-reply-target"><a href="#comment-{{ $.Scratch.Get "hasComments" }}{{ $replyLinkEnd }}" title="{{ .replyID }}"><i class="fas fa-reply"></i> {{ .replyName }}</a></h5>
               <div class="comment-timestamp"><a href="#comment-{{ $.Scratch.Get "hasComments" }}r{{ $.Scratch.Get "hasReplies" }}" title="Permalink to this comment"><time datetime="{{ .date }}">{{ dateFormat (default (i18n "shortdateFormat") .Site.Params.dateformat) .date }}</time></a></div>
               <div class="comment-content"><p>{{ .comment | markdownify }}</p></div>
               <div class="comment-reply-btn">
@@ -53,6 +57,7 @@
             </article>
           {{ end }}
         {{ end }}
+        {{ $.Scratch.Delete "replyIndices" }}
       {{ end }}
     {{ end }}
   {{ end }}

Removed JavaScript smooth scroll to keep things simple.

diff --git a/static/js/staticman.js b/static/js/staticman.js
index b874723..1e6b027 100644
--- a/static/js/staticman.js
+++ b/static/js/staticman.js
@@ -52,11 +52,4 @@
     $('input[name="fields[replyName]"]').val("");
     $('.js-form fieldset button.button').text('Submit');
   });
-
-
-  $('.comment-reply-target a[href^="#"]').click(function (){
-    targetPostID = $(this).attr('href');
-    targetID = "#" + $(targetPostID).parents('.static-comment').attr('id');
-    $('html, body').animate({ scrollTop: $(targetID).offset().top-$('nav').height() }, 500);
-  });
 })(jQuery);

VincentTam avatar Jul 29 '19 07:07 VincentTam

Improved UI with really static links.

Screenshot_2019-07-30 Huginn Theme With Staticman(1)

VincentTam avatar Jul 30 '19 18:07 VincentTam

Hey @VincentTam, Thank you so much for all your hard work! I'd love to merge this. Github is complaining about an unresolvable conflict, and I think it's just upset that you moved the .css and .js from static/* to assets/*. Can you tell me why they moved? Thank you!

halogenica avatar Sep 21 '19 06:09 halogenica

The motivation for such refactoring is the same as https://github.com/daattali/beautiful-jekyll/pull/521/commits/19c9d068ef3d9941c360a92197f8d0f0992f84eb: to avoid spam comments by moving the form action URL to JS, so that a static HTML scan performed by search bots won't find the URL. To do that, we need some Hugo code in the asset JS file to read the custom Staticman API from the site config file.

Issues to be fixed:

  1. Display issue Example: https://vincenttam.gitlab.io/post/2018-09-27-custom-katex-macros/ Screenshot from 2019-09-21 09-30-55
  2. Comments preview I've used Showdown for comments preview. However, it's not the same flavor of Hugo's version. Here's working Jekyll example of Markdown preview: https://zcrc.me/retromini/2019/05/31/opendingux-release-20190601.html#replies

VincentTam avatar Sep 21 '19 07:09 VincentTam

Hi all, and thank you @VincentTam to work on this feature

The demo you refer to is not working anymore : https://vincenttam.gitlab.io/post/2018-09-27-custom-katex-macros/

Cheers

iootaa avatar Jun 26 '20 22:06 iootaa

Can we have the ability to:

  • have up and down votes on comments and replies
  • star or rate comments and replies
  • collapse and expand comments and threads
  • add reaction using emoji icons to comments
  • display a discourse like summary of the comment thread at the top
  • display a colour-coded line to the left grouping reply threads by level
  • ability to sort thread by the user on:
    • time updating thread
    • votes
    • rating
    • reactions
  • toddle threaded and linearised format

sirinath avatar Jul 06 '20 06:07 sirinath

@sirinath yes but git is not made for huge data storage like SQL. stars accompanied by a written comment can be treated as numbered field, but I worry that FB-like likes/thumb ups would generate too much interactions, which are then transformed into an illusory "code source change", that your Git hosting site isn't made for. An SQL database is a more sensible solution.

looking back, i've put too much things into one PR. i shld hav broken it into several, but i dun hav the time to do so. my tweaked theme on GitLab at https://gitlab.com/VincentTam/beautifulhugo works well for my blog https://vincenttam.gitlab.io, so i won't bother to maintain it. as can be seen from users in the official Staticman repo, there's a strong demand for a working Staticman example. i believe leaving it untouched here might help other courageous testers, especially the sample config files staticman.yml and config.toml.

VincentTam avatar Jul 24 '20 09:07 VincentTam