diff --git a/.gitignore b/.gitignore
index ded7ea9..124bd06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
node_modules
src/css/custom-props.css
_site
-.DS_Store
\ No newline at end of file
+.DS_Store
+.cache
\ No newline at end of file
diff --git a/config/filters/dates.js b/config/filters/dates.js
index b4c7cde..88d9e14 100644
--- a/config/filters/dates.js
+++ b/config/filters/dates.js
@@ -4,4 +4,15 @@ module.exports = function(eleventyConfig) {
eleventyConfig.addFilter('dateDisplay', date => new Date(date).toLocaleDateString('en-GB', {
"dateStyle": "short"
}));
+
+ eleventyConfig.addFilter('dateTimeDisplay', date => new Date(date).toLocaleString('en-GB', {
+ 'dateStyle': 'short',
+ 'timeStyle': 'short',
+ }));
+
+ eleventyConfig.addFilter('timeDisplay', date => new Date(date).toLocaleTimeString('en-GB', {
+ 'hour': '2-digit',
+ 'minute': 'numeric',
+ 'hour12': true
+ }));
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 52e4361..c10548c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,9 +8,6 @@
"name": "whimsy",
"version": "1.0.0",
"license": "ISC",
- "dependencies": {
- "html-entities": "^2.3.3"
- },
"devDependencies": {
"@11ty/eleventy": "^2.0.0",
"@11ty/eleventy-fetch": "^3.0.0",
@@ -19,6 +16,7 @@
"@11ty/eleventy-plugin-syntaxhighlight": "^4.2.0",
"@toycode/markdown-it-class": "^1.2.4",
"autoprefixer": "^10.4.13",
+ "lodash": "^4.17.21",
"markdown-it-abbr": "^1.0.4",
"markdown-it-anchor": "^8.6.6",
"markdown-it-eleventy-img": "^0.9.0",
@@ -1998,11 +1996,6 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
- "node_modules/html-entities": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
- "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="
- },
"node_modules/html-escaper": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
@@ -2683,6 +2676,12 @@
"node": ">=4"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
"node_modules/lodash.chunk": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
@@ -6672,11 +6671,6 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
- "html-entities": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
- "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="
- },
"html-escaper": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
@@ -7160,6 +7154,12 @@
}
}
},
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
"lodash.chunk": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
diff --git a/package.json b/package.json
index 2a17a1c..af2e814 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"@11ty/eleventy-plugin-syntaxhighlight": "^4.2.0",
"@toycode/markdown-it-class": "^1.2.4",
"autoprefixer": "^10.4.13",
+ "lodash": "^4.17.21",
"markdown-it-abbr": "^1.0.4",
"markdown-it-anchor": "^8.6.6",
"markdown-it-eleventy-img": "^0.9.0",
@@ -36,8 +37,5 @@
"postcss-nested": "^6.0.0",
"prettier": "^2.8.3",
"tailwindcss": "^3.2.4"
- },
- "dependencies": {
- "html-entities": "^2.3.3"
}
}
diff --git a/src/_data/posts.js b/src/_data/posts.js
index e85fed7..9fe46b8 100644
--- a/src/_data/posts.js
+++ b/src/_data/posts.js
@@ -1,6 +1,88 @@
+const EleventyFetch = require('@11ty/eleventy-fetch');
+const fs = require('fs');
+const merge = require('lodash/merge')
+
const wordpressPassword = process.env.WORDPRESS_PASSWORD;
const auth = Buffer.from(`lewis:${wordpressPassword}`).toString('base64');
+const dateSort = (a, b) => new Date(b.date) - new Date(a.date);
+
+class PostCache {
+ constructor() {
+ this.readCache();
+ }
+
+ readCache() {
+ if (!fs.existsSync(".cache/wordpress_post_fetch.json")) {
+ this.last_read_date = null;
+ this.posts = {};
+ } else {
+ const data = JSON.parse(fs.readFileSync(".cache/wordpress_post_fetch.json"));
+ this.last_read_date = new Date(data.last_read_date);
+ this.posts = data.posts;
+ }
+ }
+
+ writeCache() {
+ fs.writeFileSync(".cache/wordpress_post_fetch.json", JSON.stringify(this, null, 2));
+ }
+
+ async fetchCommentsByType(type = "comment") {
+ const params = new URLSearchParams();
+ params.set("per_page", 100);
+ params.set("type", type);
+
+ if (this.last_read_date) {
+ params.set("modified_after", this.last_read_date.toISOString());
+ }
+
+ const response = await fetch(`https://lewisdale.dev/wp-json/wp/v2/comments?${params.toString()}`, {
+ headers: {
+ "Authorization": `Basic ${auth}`
+ }
+ });
+ return await response.json()
+ }
+
+ async fetchComments() {
+ const comments = [...await this.fetchCommentsByType(), ...await this.fetchCommentsByType("webmention")];
+
+ comments.forEach(comment => {
+ if (this.posts[comment.post]) {
+ this.posts[comment.post].comments[comment.id] = comment;
+ }
+ });
+ }
+
+ async fetchPosts() {
+ const params = new URLSearchParams();
+ params.set("per_page", 100);
+
+ if (this.last_read_date) {
+ params.set("modified_after", this.last_read_date.toISOString());
+ }
+
+ const response = await fetch(`https://lewisdale.dev/wp-json/wp/v2/posts?${params.toString()}`, {
+ headers: {
+ "Authorization": `Basic ${auth}`
+ }
+ });
+ const posts = await response.json();
+
+ posts.forEach(post => {
+ this.posts[post.id] = merge({ comments: {} }, this.posts[post.id], post);
+ });
+ }
+
+ async fetchLatest() {
+ await this.fetchPosts();
+ await this.fetchComments();
+
+ this.last_read_date = new Date();
+ this.writeCache();
+ }
+}
+
const mapComment = comment => ({
author: {
name: comment.author_name,
@@ -9,46 +91,27 @@ const mapComment = comment => ({
},
content: comment.content.rendered,
canonical: comment.meta.semantic_linkbacks_canonical,
- date: comment.data,
+ date: comment.date,
});
-const comments = async pid => {
- const response = await fetch(`https://lewisdale.dev/wp-json/wp/v2/comments?per_page=100&post=${pid}`);
- return (await response.json()).map(mapComment);
-}
-
-const webmentions = async (pid) => {
- const response = await fetch(`https://lewisdale.dev/wp-json/wp/v2/comments?per_page=100&post=${pid}&type=Webmention`, {
- headers: {
- "Authorization": `Basic ${auth}`
- }
- });
-
- return (await response.json())
- .reduce((comments, comment) => {
- if (!comments[comment.meta.semantic_linkbacks_type]) {
- comments[comment.meta.semantic_linkbacks_type] = [];
- }
-
- comments[comment.meta.semantic_linkbacks_type].push(mapComment(comment));
- return comments;
- }, { like: [], repost: [] });
-}
-
-const getComments = async pid => {
- return {
- comments: await comments(pid),
- ...(await webmentions(pid))
- }
-}
module.exports = async () => {
- const response = await fetch("https://lewisdale.dev/wp-json/wp/v2/posts?per_page=100", {
- headers: {
- "Authorization": `Basic ${auth}`
- }
- });
-
- const posts = (await response.json());
- return Promise.all(posts.map(async post => ({...post, comments: await getComments(post.id) })));
+ const cache = new PostCache();
+ await cache.fetchLatest();
+
+ return Object.values(cache.posts)
+ .sort(dateSort)
+ .map(post => ({
+ ...post,
+ comments: Object.values(post.comments)
+ .sort(dateSort)
+ .reduce((comments, comment) => {
+ if (!comments[comment.meta.semantic_linkbacks_type]) {
+ comments[comment.meta.semantic_linkbacks_type] = [];
+ }
+
+ comments[comment.meta.semantic_linkbacks_type].push(mapComment(comment));
+ return comments;
+ }, { like: [], reply: [], repost: [] })
+ }));
};
\ No newline at end of file
diff --git a/src/_includes/base.njk b/src/_includes/base.njk
index 8d52a83..884b6ba 100644
--- a/src/_includes/base.njk
+++ b/src/_includes/base.njk
@@ -9,7 +9,13 @@
{% endif %}
+
+
+
+
+
+
diff --git a/src/_includes/post.njk b/src/_includes/post.njk
index 380baca..a7d074a 100644
--- a/src/_includes/post.njk
+++ b/src/_includes/post.njk
@@ -3,6 +3,7 @@ layout: base.njk
includePrism: true
eleventyComputed:
title: "{{ post.title.rendered | safe }}"
+ description: "{{ post.yoast_head_json.description }}"
---
@@ -10,9 +11,64 @@ eleventyComputed:
{{ content | safe }}
-
+
+ Responses
+
+ {% if post.comments.like | length %}
+
+
Likes
+
+
+ {% for like in post.comments.like %}
+
+
+
+ {% endfor %}
+
+
+ {% endif %}
+ {% if post.comments.repost | length %}
+
+
Reposts
+
+
+ {% for like in post.comments.repost %}
+
+
+
+ {% endfor %}
+
+
+ {% endif %}
+
+ {% if post.comments.reply | length %}
+
+
Replies
+
+
+ {% for reply in post.comments.reply %}
+
+ -
+
+
+
+
+ {% set date = reply.date | parseDate %}
+
{{ reply.author.name }} on {{ date | dateDisplay }} at {{ date | timeDisplay }}
+
Original comment
+
{{ reply.content | safe }}
+
+
+ {% endfor %}
+
+
+ {% endif %}
+
+
+
About Lewis
{% image metadata.author.avatar, "My face", "u-photo box circle", "150px", [150] %}
-
+
+
\ No newline at end of file
diff --git a/src/css/exceptions/overlaps.css b/src/css/exceptions/overlaps.css
new file mode 100644
index 0000000..55ef898
--- /dev/null
+++ b/src/css/exceptions/overlaps.css
@@ -0,0 +1,14 @@
+.overlaps {
+ gap: 0;
+ max-width: 30rem;
+ padding-left: 1rem;
+
+ > * {
+ display: inline-block;
+ max-width: 3rem;
+ }
+
+ > * {
+ margin-inline-start: -1rem;
+ }
+}
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
index 6c2af1b..4308b19 100644
--- a/src/index.html
+++ b/src/index.html
@@ -24,8 +24,8 @@ layout: base.njk
Recent Posts