beautifulhugo
beautifulhugo copied to clipboard
[Feature] Staticman Comment Reply
Demo site
https://vincenttam.gitlab.io/bhdemo
New features
- comment reply
- comment preview
Bug fixes and modifications
- #221
- dancwilliams/networkhobo#373
- added standard LaTeX math delimiters
$...$
to KaTeX's defaultdelimiters
.
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.
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">
inlayouts/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 HTMLchildren()
of any.static-comment
. - I've changed
{{ if not .parent }}
inlayouts/partials/staticman-comments.html
(introduced at d68cf2e04dd2d64efa0c8e6312aa271402fb06c0 by @badele) to{{ if not .replyThread }}
becauseoptions[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 ofthreadID
because a "main comment" starts a thread, so it belongs to a thread, thus it would look a bit strange without athreadID
. - 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.
- I've chosen
- CSS can be improved, but the logic is already there.
- I've introduced an
offset
instatic/js/staticman.js
so that the anchor target won't get covered by thenavbar
. 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 ananimation
(the way I prefered) so that I can jump to a different element (the top of the post) by feeding anotherhref
(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/
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);
Improved UI with really static links.
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!
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:
- Display issue
Example: https://vincenttam.gitlab.io/post/2018-09-27-custom-katex-macros/
- 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
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
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 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
.