summaryrefslogtreecommitdiff
path: root/haunt
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2022-05-07 21:53:34 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2022-05-08 19:10:19 -0400
commitf6bd35e8e10faf4db80d6c8ccb45a5beae44c2be (patch)
tree574bff4e3bb8fc98d2c38f1d91e2d938bc4a5caa /haunt
parent96ad1a33e34ddcdd06cf31855e680a9b1b45c36a (diff)
[scheme] Initial comments API
Diffstat (limited to 'haunt')
-rw-r--r--haunt/jakob/builder/blog.scm31
-rw-r--r--haunt/static/js/local.js110
2 files changed, 141 insertions, 0 deletions
diff --git a/haunt/jakob/builder/blog.scm b/haunt/jakob/builder/blog.scm
index 8f02a80..2e54998 100644
--- a/haunt/jakob/builder/blog.scm
+++ b/haunt/jakob/builder/blog.scm
@@ -80,6 +80,37 @@
"."))
(article ,(post-sxml post))
(section
+ (@ (id "comments"))
+ (h2 "Comments for this Page")
+ (ul (@ (id "comment-container")))
+ (form
+ (@ (action "https://jakob.space/api/comment")
+ (method "post"))
+ (label (@ (for "name")) "Name:")
+ (br)
+ (input (@ (name "name") (id "name") (type "text")))
+ (br)
+ (label (@ (for "email")) "Email (optional; only used for Gravatar):")
+ (br)
+ (input (@ (name "email") (id "email") (type "text")))
+ (br)
+ (label (@ (for "url")) "Homepage (optional):")
+ (br)
+ (input (@ (name "url") (id "url") (type "text")))
+ (br)
+ (label (@ (for "comment")) "Comment (Markdown supported):")
+ (br)
+ (textarea (@ (name "comment") (id "comment") (rows "4") (cols "50") (maxlength "1024")))
+ (br)
+ (label (@ (for "captcha")) "Captcha: Please integrate the following definite integral.")
+ (br)
+ (img (@ (id "captcha") (alt "captcha-image")))
+ (br)
+ (input (@ (name "captcha") (id "captcha") (type "text")))
+ (br)
+ (input (@ (value "Submit") (type "submit"))))
+ ,(script "local.js"))
+ (section
(@ (id "webmention"))
(h2 ,(hyperlink "https://indieweb.org/Webmention" "Webmentions")
" for this Page")
diff --git a/haunt/static/js/local.js b/haunt/static/js/local.js
new file mode 100644
index 0000000..51e0ea1
--- /dev/null
+++ b/haunt/static/js/local.js
@@ -0,0 +1,110 @@
+/*
+ * local.js -- Fetch and display local comments.
+ * Copyright © 2022 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+function getData(url, callback) {
+ let xhr = new XMLHttpRequest();
+ xhr.onload = function(data) {
+ callback(data);
+ }
+ xhr.onerror = function(error) {
+ throw new Error(`Request failed: ${error}`);
+ }
+}
+
+function makeComment(comment) {
+ const strip = (uri) => {
+ const sep = "://";
+ return uri.substring(uri.indexOf(sep) + sep.length);
+ };
+
+ const element = (type, attributes) => {
+ let res = document.createElement(type);
+ for (const attribute in attributes) {
+ res.setAttribute(attribute, attributes[attribute]);
+ }
+ return res;
+ };
+
+ // Create the h-card section.
+ let avatar = element("img", {
+ "class": "u-photo",
+ "src": `https://www.gravatar.com/avatar/${comment.iconHash}?s=200`
+ });
+
+ let authorName = element("a", {
+ "class": "p-name u-url",
+ "href": comment.authorUrl
+ });
+ authorName.textContent = comment.authorName;
+
+ let authorURI = element("a", {
+ "class": "author_url",
+ "href": comment.author.url
+ });
+ authorURI.textContent = strip(comment.author.url);
+
+ let hCardContainer = element("div", {
+ "class": "p-author h-card author"
+ });
+ hCardContainer.appendChild(avatar);
+ hCardContainer.appendChild(authorName);
+ hCardContainer.appendChild(authorURI);
+
+ // Create the content section.
+ let contentContainer = element("div", {
+ "class": "e-content p-name comment-content",
+ });
+
+ contentContainer.textContent = comment.content;
+
+ // Create the metaline section.
+ let pubTime = comment.published;
+ let time = element("time", {
+ "class": "dt-published",
+ "datetime": pubTime,
+ });
+ time.textContent = (new Date(pubTime)).toString();
+
+ let linkBack = element("a", {
+ "class": "u-url",
+ "href": comment.url
+ });
+ linkBack.appendChild(time);
+
+ let metalineContainer = element("div", {
+ "class": "metaline"
+ });
+ metalineContainer.appendChild(linkBack);
+
+ // Put it all together.
+ let wrapper = element("li", {
+ "class": "p-comment h-cite comment",
+ });
+ wrapper.appendChild(hCardContainer);
+ wrapper.appendChild(contentContainer);
+ wrapper.appendChild(metalineContainer);
+
+ return wrapper;
+}
+
+getData("http://localhost:8081/api/challenge", (b64data) => {
+ console.log("Here2");
+ document.getElementById("captcha").src = 'data:image/png;base64,' + b64data;
+});
+console.log("Here1");