summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2019-05-11 15:27:03 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2019-05-11 15:46:31 -0400
commit9e0edbe4140753ea739f022c4847837a7a1f373c (patch)
tree6a85ae52ca775c9b7df67edfd518c16a1e541c5c
parent8d4f38027b3baeead5da2399431649241ebab73e (diff)
Add initial implementation of Webmention inbox
-rw-r--r--haunt/css/jakob.css15
-rw-r--r--haunt/custom/theme.scm6
-rw-r--r--haunt/haunt.scm1
-rw-r--r--haunt/js/webmention.js123
4 files changed, 144 insertions, 1 deletions
diff --git a/haunt/css/jakob.css b/haunt/css/jakob.css
index 44dc569..b2d2ba3 100644
--- a/haunt/css/jakob.css
+++ b/haunt/css/jakob.css
@@ -240,3 +240,18 @@ figcaption {
#MathJax-Element-4-Frame {
padding-right: 8px;
}
+
+/* Webmention */
+
+ul#webmention-container {
+ list-style-type: none;
+}
+
+ul#webmention-container img.u-photo {
+ width: 4rem;
+ float: left;
+}
+
+ul#webmention-container div.p-author * {
+ padding-right: 1rem;
+}
diff --git a/haunt/custom/theme.scm b/haunt/custom/theme.scm
index e44f602..fe4b53a 100644
--- a/haunt/custom/theme.scm
+++ b/haunt/custom/theme.scm
@@ -123,7 +123,11 @@ license.")
`(li ,(link tag (format #f "/tag-~a.html" tag))))
(post-ref post 'tags)))))
(div (@ (class "post"))
- ,(post-sxml post))))
+ ,(post-sxml post))
+ (hr)
+ (h2 ,(link "Webmentions" "https://indieweb.org/Webmention") " for this Page")
+ (ul (@ (id "webmention-container")))
+ (script (@ (src "/js/webmention.js")))))
#:collection-template
(lambda (site title posts prefix)
(define (post-uri post)
diff --git a/haunt/haunt.scm b/haunt/haunt.scm
index c618ab0..225a4a2 100644
--- a/haunt/haunt.scm
+++ b/haunt/haunt.scm
@@ -130,6 +130,7 @@
(static-page "Projects" "projects")
(static-directory "css")
(static-directory "fonts")
+ (static-directory "js")
(static-directory "images")
(lambda (site posts)
(make-asset "other/gpg.txt" "/gpg.txt"))))
diff --git a/haunt/js/webmention.js b/haunt/js/webmention.js
new file mode 100644
index 0000000..5986628
--- /dev/null
+++ b/haunt/js/webmention.js
@@ -0,0 +1,123 @@
+/*
+ * webmention.js -- Fetch and display mentions from webmention.io.
+ * Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.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/>.
+ */
+
+// TODO: Page-specific comments.
+// TODO: Build up from aliases, etc.
+const REFURI = "jakob.space";
+const APIURI = [
+ "https://webmention.io/api/mentions.jf2?",
+ `target[]=http://${REFURI}&`,
+ `&target[]=https://${REFURI}`
+].join("");
+
+function getData(url, callback) {
+ if (fetch) {
+ fetch(url).then(function(response) {
+ if (response.status >= 200 && response.status < 300) {
+ return Promise.resolve(response);
+ } else {
+ return Promise.reject(new Error(`Request failed: ${response.statusText}`));
+ }
+ }).then(function(response) {
+ return response.json();
+ }).then(callback);
+ } else {
+ let xhr = new XMLHttpRequest();
+ xhr.onload = function(data) {
+ callback(JSON.parse(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": comment.author.photo
+ });
+
+ let authorName = element("a", {
+ "class": "p-name u-url",
+ "href": comment.author.url
+ });
+ authorName.innerHTML = comment.author.name;
+
+ let authorURI = element("a", {
+ "class": "author_url",
+ "href": comment.author.url
+ });
+ authorURI.innerHTML = 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.innerHTML = comment.content.text;
+
+ // Create the metaline section.
+ let time = element("time", {
+ "class": "dt-published",
+ "datetime": comment.published
+ });
+ time.innerHTML = (new Date(comment.published)).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;
+}