diff --git a/feeds.json b/feeds.json
index f245163..b823df1 100644
--- a/feeds.json
+++ b/feeds.json
@@ -38,5 +38,9 @@
"author_name": "The HullCSS team",
"github_username": "hullcss",
"feed_uri": "https://hullcss.org/feed.xml"
+ {
+ "author_name": "Eirika Doe",
+ "github_username": "EirikaDoesntCode",
+ "feed_uri": "https://edcblog.netlify.app/feed/feed.xml"
}
]
diff --git a/src/bloggers.11tydata.js b/src/bloggers.11tydata.js
new file mode 100644
index 0000000..55b1605
--- /dev/null
+++ b/src/bloggers.11tydata.js
@@ -0,0 +1,47 @@
+"use strict";
+
+const path = require("path");
+const fs = require("fs");
+
+const fetch_json = require("./lib/fetch_json.js");
+const shuffle = require("./lib/shuffle.js");
+
+async function fetch_info(blogger) {
+ if(typeof blogger.github_username !== "string") return;
+
+ const github_userdata = (await fetch_json(`https://api.github.com/users/${blogger.github_username}`)).body;
+
+ if(typeof github_userdata.message === "string") {
+ console.error(github_userdata.message);
+ }
+
+ blogger.bio = github_userdata.bio;
+ blogger.url_blog = github_userdata.blog;
+ blogger.url_github = github_userdata.html_url;
+ blogger.url_twitter = github_userdata.twitter_username === null ? null : `https://twitter.com/@${github_userdata.twitter_username.replace(/^@/, "")}`;
+ blogger.url_avatar = github_userdata.avatar_url;
+
+ // If the link to the blog doesn't include a protocol, default to https.
+ // If this breaks your blog, then you should enable https to fix the issue.
+ // ALL Internet traffic should be encrypted. Your blog is not an exception.
+ if(blogger.url_blog.search(/^[a-zA-Z]+:\/\//) === -1)
+ blogger.url_blog = `https://${blogger.url_blog}`;
+
+ if(typeof blogger.url_blog !== "string" || blogger.url_blog.length == 0)
+ blogger.url_blog = null;
+}
+
+module.exports = async function() {
+ const feeds_data = JSON.parse(await fs.promises.readFile(path.resolve(__dirname, "../feeds.json"), "utf-8"));
+ await Promise.all(feeds_data.map(fetch_info));
+
+ shuffle(feeds_data); // Don't give any 1 person the advantage
+
+ return {
+ layout: "main.njk",
+ title: "Bloggers",
+ tags: "navigable",
+ date: "2001-01-01",
+ bloggers: feeds_data
+ }
+}
\ No newline at end of file
diff --git a/src/bloggers.html b/src/bloggers.html
new file mode 100644
index 0000000..2f03c17
--- /dev/null
+++ b/src/bloggers.html
@@ -0,0 +1,27 @@
+
Check out these cool people who are featured here on hullblogs.com!
+
+
+ {% for blogger in bloggers %}
+
+
![{{ blogger.author_name | htmlentities }}]({% asset blogger.url_avatar %})
+
+
{{ blogger.author_name | htmlentities }}
+
+ {% if blogger.url_blog %}
+
+ {% endif %}
+
+
+
+
+
+
+ {% if blogger.url_twitter %}
+
+ {% endif %}
+
+
{{ blogger.bio }}
+
+
+ {% endfor %}
+
\ No newline at end of file
diff --git a/src/css/theme.css b/src/css/theme.css
index 040d662..3db8aec 100644
--- a/src/css/theme.css
+++ b/src/css/theme.css
@@ -208,6 +208,28 @@ nav > span[aria-current] > a {
text-decoration: none;
}
+.blogger {
+ display: flex;
+ flex-direction: row;
+ margin: 1.5em;
+}
+.blogger:nth-child(even) {
+ background: var(--shadow);
+}
+.blogger-info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ margin: 0 0.5em;
+ gap: 0.5em;
+}
+.blogger-icons {
+ display: flex;
+ flex-direction: row;
+ gap: 0.5em;
+}
+.blogger-bio { flex: 1; }
+
footer {
padding-bottom: 3em;
grid-area: footer;
@@ -290,6 +312,7 @@ input[type=text], input[type=number], textarea
.medium-icon-abs { width: 1.25em; height: 1.25em; vertical-align: middle; }
.large-icon { max-width: 1.5em; max-height: 1.5em; vertical-align: middle; }
.tiny-image { max-width: 5em; max-height: 5em; }
+.kinda-tiny-image{ max-width: 7em; max-height: 7em; }
.small-image { max-width: 10em; max-height: 10em; }
.medium-image { max-width: 20em; max-height: 20em; }
.large-image { max-width: 30em; max-height: 30em; }
diff --git a/src/images/rss.svg b/src/images/rss.svg
new file mode 100644
index 0000000..4f1c279
--- /dev/null
+++ b/src/images/rss.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/twitter.svg b/src/images/twitter.svg
new file mode 100644
index 0000000..59c727f
--- /dev/null
+++ b/src/images/twitter.svg
@@ -0,0 +1,65 @@
+
+
+
+
diff --git a/src/lib/fetch_json.js b/src/lib/fetch_json.js
new file mode 100644
index 0000000..aa075bc
--- /dev/null
+++ b/src/lib/fetch_json.js
@@ -0,0 +1,23 @@
+const fs = require("fs");
+const path = require("path");
+const os = require("os");
+
+const phin = require("phin");
+
+async function fetch_json(url) {
+ let package = JSON.parse(await fs.promises.readFile(
+ path.join(path.dirname(path.dirname(__dirname)), "package.json"), "utf8"
+ ));
+
+ return (await phin({
+ url,
+ headers: {
+ "user-agent": `HullBlogsStaticBuilder/${package.version} (Node.js/${process.version}; ${os.platform()} ${os.arch()}) eleventy/${package.dependencies["@11ty/eleventy"].replace(/\^/, "")}`
+ },
+ followRedirects: true,
+ parse: "json"
+ }));
+}
+
+
+module.exports = fetch_json;
diff --git a/src/lib/shuffle.js b/src/lib/shuffle.js
new file mode 100644
index 0000000..1395c65
--- /dev/null
+++ b/src/lib/shuffle.js
@@ -0,0 +1,22 @@
+"use strict";
+
+
+function shuffle(array) {
+ let currentIndex = array.length, randomIndex;
+
+ // While there remain elements to shuffle.
+ while (currentIndex != 0) {
+
+ // Pick a remaining element.
+ randomIndex = Math.floor(Math.random() * currentIndex);
+ currentIndex--;
+
+ // And swap it with the current element.
+ [array[currentIndex], array[randomIndex]] = [
+ array[randomIndex], array[currentIndex]];
+ }
+
+ return array;
+}
+
+module.exports = shuffle;
\ No newline at end of file