-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1b2e967
commit d731856
Showing
12 changed files
with
290 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
_cache/ | ||
_site/ | ||
node_modules/ | ||
package-lock.json | ||
*/.DS_Store | ||
.DS_Store | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const { DateTime } = require("luxon"); | ||
|
||
module.exports = { | ||
getWebmentionsForUrl: (webmentions, url) => { | ||
return webmentions.children.filter(entry => entry['wm-target'] === url) | ||
}, | ||
isOwnWebmention: (webmention) => { | ||
const urls = [ | ||
'https://sia.codes', | ||
'https://twitter.com/thegreengreek' | ||
] | ||
const authorUrl = webmention.author ? webmention.author.url : false | ||
// check if a given URL is part of this site. | ||
return authorUrl && urls.includes(authorUrl) | ||
}, | ||
size: (mentions) => { | ||
return !mentions ? 0 : mentions.length | ||
}, | ||
webmentionsByType: (mentions, mentionType) => { | ||
return mentions.filter(entry => !!entry[mentionType]) | ||
}, | ||
readableDateFromISO: (dateStr, formatStr = "dd LLL yyyy 'at' hh:mma") => { | ||
return DateTime.fromISO(dateStr).toFormat(formatStr); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,17 @@ | ||
{ | ||
"title": "Sia Karamalegos, Freelance Web Performance Engineer", | ||
"url": "https://sia.codes/", | ||
"url": "https://sia.codes", | ||
"description": "Sia is a freelance developer and web performance engineer, speaker, teacher, community organizer, and Google Developers Expert in Web Technologies.", | ||
"feed": { | ||
"subtitle": "Sia is a freelance developer and web performance engineer, speaker, teacher, community organizer, and Google Developers Expert in Web Technologies.", | ||
"filename": "feed.xml", | ||
"path": "/feed/feed.xml", | ||
"url": "https://myurl.com/feed/feed.xml", | ||
"id": "https://myurl.com/" | ||
"url": "https://sia.codes/feed/feed.xml", | ||
"id": "https://sia.codes/" | ||
}, | ||
"author": { | ||
"name": "Sia Karamalegos", | ||
"email": "siakaramalegos@gmail.com" | ||
} | ||
}, | ||
"domain": "sia.codes" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
const fs = require('fs') | ||
const fetch = require('node-fetch') | ||
const unionBy = require('lodash/unionBy') | ||
const domain = require('./metadata.json').domain | ||
|
||
// Load .env variables with dotenv | ||
require('dotenv').config() | ||
|
||
// Define Cache Location and API Endpoint | ||
const CACHE_FILE_PATH = '_cache/webmentions.json' | ||
const API = 'https://webmention.io/api' | ||
const TOKEN = process.env.WEBMENTION_IO_TOKEN | ||
|
||
async function fetchWebmentions(since, perPage = 10000) { | ||
// If we dont have a domain name or token, abort | ||
if (!domain || !TOKEN) { | ||
console.warn('>>> unable to fetch webmentions: missing domain or token') | ||
return false | ||
} | ||
|
||
let url = `${API}/mentions.jf2?domain=${domain}&token=${TOKEN}&per-page=${perPage}` | ||
if (since) url += `&since=${since}` // only fetch new mentions | ||
|
||
const response = await fetch(url) | ||
if (response.ok) { | ||
const feed = await response.json() | ||
console.log(`>>> ${feed.children.length} new webmentions fetched from ${API}`) | ||
return feed | ||
} | ||
|
||
return null | ||
} | ||
|
||
// Merge fresh webmentions with cached entries, unique per id | ||
function mergeWebmentions(a, b) { | ||
return unionBy(a.children, b.children, 'wm-id') | ||
} | ||
|
||
// save combined webmentions in cache file | ||
function writeToCache(data) { | ||
const dir = '_cache' | ||
const fileContent = JSON.stringify(data, null, 2) | ||
// create cache folder if it doesnt exist already | ||
if (!fs.existsSync(dir)) { | ||
fs.mkdirSync(dir) | ||
} | ||
// write data to cache json file | ||
fs.writeFile(CACHE_FILE_PATH, fileContent, err => { | ||
if (err) throw err | ||
console.log(`>>> webmentions cached to ${CACHE_FILE_PATH}`) | ||
}) | ||
} | ||
|
||
// get cache contents from json file | ||
function readFromCache() { | ||
if (fs.existsSync(CACHE_FILE_PATH)) { | ||
const cacheFile = fs.readFileSync(CACHE_FILE_PATH) | ||
return JSON.parse(cacheFile) | ||
} | ||
|
||
// no cache found. | ||
return { | ||
lastFetched: null, | ||
children: [] | ||
} | ||
} | ||
|
||
module.exports = async function () { | ||
console.log('>>> Reading webmentions from cache...'); | ||
|
||
const cache = readFromCache() | ||
|
||
if (cache.children.length) { | ||
console.log(`>>> ${cache.children.length} webmentions loaded from cache`) | ||
} | ||
|
||
// Only fetch new mentions in production | ||
if (process.env.NODE_ENV === 'production') { | ||
console.log('>>> Checking for new webmentions...'); | ||
const feed = await fetchWebmentions(cache.lastFetched) | ||
if (feed) { | ||
const webmentions = { | ||
lastFetched: new Date().toISOString(), | ||
children: mergeWebmentions(cache, feed) | ||
} | ||
|
||
writeToCache(webmentions) | ||
return webmentions | ||
} | ||
} | ||
|
||
return cache | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<article class="webmention {% if webmention|isOwnWebmention %}webmention--own{% endif %}" id="webmention-{{ webmention['wm-id'] }}"> | ||
<div class="webmention__meta"> | ||
{% if webmention.author %} | ||
{% if webmention.author.photo %} | ||
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy"> | ||
{% else %} | ||
<img src="{{ '/img/avatar.svg' | url }}" alt="" width="48" height="48"> | ||
{% endif %} | ||
<span> | ||
<a class="h-card u-url" {% if webmention.url %}href="{{ webmention.url }}" {% endif %} target="_blank" rel="noopener noreferrer"><strong class="p-name">{{ webmention.author.name }}</strong></a> | ||
</span> | ||
{% else %} | ||
<span> | ||
<strong>Anonymous</strong> | ||
</span> | ||
{% endif %} | ||
|
||
{% if webmention.published %} | ||
<time class="postlist-date" datetime="{{ webmention.published }}"> | ||
{{ webmention.published | readableDateFromISO }} | ||
</time> | ||
{% endif %} | ||
</div> | ||
<div> | ||
{{ webmention.content.text }} | ||
</div> | ||
</article> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<div class="webmentions content-grid-sibling" id="webmentions"> | ||
|
||
{% set mentions = webmentions | getWebmentionsForUrl(metadata.url + webmentionUrl) %} | ||
{% set reposts = mentions | webmentionsByType('repost-of') %} | ||
{% set repostsSize = reposts | size %} | ||
{% set likes = mentions | webmentionsByType('like-of') %} | ||
{% set likesSize = likes | size %} | ||
{% set replies = mentions | webmentionsByType('in-reply-to') %} | ||
{% set repliesSize = replies | size %} | ||
|
||
|
||
{% if likesSize > 0 %} | ||
<div class="webmentions__facepile"> | ||
<h3{% if repostsSize > 11 or likesSize > 11 %} class="webmentions__facepile__squish" {% endif %}>{{ likesSize }} | ||
Like{% if likesSize != 1 %}s{% endif %}</h3> | ||
|
||
{% for webmention in likes %} | ||
|
||
{% if webmention.url != "" %} | ||
<a class="h-card u-url link-u-exempt" href="{{ webmention.url }}" target="_blank" rel="noopener noreferrer"> | ||
{% endif %} | ||
|
||
{% if webmention.author.photo %} | ||
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy"> | ||
{% else %} | ||
<img src="{{ '/img/avatar.svg' | url }}" alt="" width="48" height="48"> | ||
{% endif %} | ||
|
||
{% if webmention.url != "" %} | ||
</a> | ||
{% endif %} | ||
{% endfor %} | ||
</div> | ||
{% endif %} | ||
|
||
{% if repostsSize > 0 %} | ||
<div class="webmentions__facepile"> | ||
<h3{% if repostsSize > 11 or likesSize > 11 %} class="webmentions__facepile__squish" {% endif %}>{{ repostsSize }} Retweet{% if repostsSize != 1 %}s{% endif %}</h3> | ||
|
||
{% for webmention in reposts %} | ||
{% if webmention.url != "" %} | ||
<a class="h-card u-url link-u-exempt" href="{{ webmention.url }}" target="_blank" rel="noopener noreferrer"> | ||
{% endif %} | ||
|
||
{% if webmention.author.photo %} | ||
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy"> | ||
{% else %} | ||
<img src="{{ '/img/avatar.svg' | url }}" alt="" width="48" height="48"> | ||
{% endif %} | ||
{% if webmention.url != "" %} | ||
</a> | ||
{% endif %} | ||
{% endfor %} | ||
</div> | ||
{% endif %} | ||
|
||
{% if repliesSize > 0 %} | ||
<div class="webmention-replies"> | ||
<h3>{{ repliesSize }} {% if repliesSize == "1" %}Reply{% else %}Replies{% endif %}</h3> | ||
|
||
{% for webmention in replies %} | ||
{% include 'webmention.njk' %} | ||
{% endfor %} | ||
</div> | ||
{% endif %} | ||
|
||
<p>These are <a href="https://indieweb.org/Webmention">webmentions</a> via the <a href="https://indieweb.org/">IndieWeb</a> and <a href="https://webmention.io/">webmention.io</a>. Mention this post from your site:</p> | ||
|
||
<form action="https://webmention.io/sia.codes/webmention" method="post" class="form-webmention"> | ||
<label for="form-webmention-source">URL</label><br> | ||
<input id="form-webmention-source" type="url" name="source" placeholder="https://example.com" required> | ||
<input type="hidden" name="target" value="https://sia.codes/{{ page.url }}"> | ||
<input type="submit" class="button button-small" value="Send Webmention"> | ||
</form> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
const fs = require('fs') | ||
fs.writeFileSync('../.env', `WEBMENTION_IO_TOKEN=${process.env.WEBMENTION_IO_TOKEN}\n`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters