11 tyブログにおけるウェブメンテーションの実装
41607 ワード
私たちはwhat are Webmentionsに導入しました、これを使用して、このブログでそれらを実装しましょう.
次のようになります.
Aaron Pareckiは、この素晴らしい無料ツールwebmention.ioと呼ばれました.これは、Webを受信するホストのソリューションです.
サインアップはindie-authを使用していますので、以下のように我々のウェブサイトにリンクしなければなりません.
一度、我々は我々のドメインに我々の2つの関連を加える必要があります
それで、今、我々はウェブ言及を受けることができます、しかし、すべての正直で、WHOはWebReferenceを我々に送りますか?
人々のウェブサイトに私たちのURLをつぶやき変換しましょう!
我々は、bridgyのようなホストサービスを使用することができます.
ちょうどTwitterのアイコンをクリックしてログインします.
その後、あなたのウェブサイトや世論調査のTwitterをクロールすることができます.
実際のウェブサイトでの応答は以下のようになります.
すべての設定を持っているので、WebReadingのためのすべてのウェブメンテーションズを集めます.入出力API.
では、カスタムデータファイルを
それを
この関数は、私たちの11回目のブログを構築したら実行されます.
このデータファイルを作成することで、
前述のように、我々は現在
そして、私の場合は、次の要素をウェブサイトから分割します.は、 が好きですリポスト/retweets は、 に言及して、答えます
ブログページのレイアウトで次のように追加します.
まず、現在のページの完全なURLを取得する必要があります.
我々は、それから部分的に我々の
私のブログを読んでくれてありがとう.私の電子メール会報を購読して、Facebook
Note: I used Max Böck's article and his code to implement them on my blog.
次のようになります.
ステップ1。ウェブ言及のサインアップio
Aaron Pareckiは、この素晴らしい無料ツールwebmention.ioと呼ばれました.これは、Webを受信するホストのソリューションです.
サインアップはindie-authを使用していますので、以下のように我々のウェブサイトにリンクしなければなりません.
<a href="https://twitter.com/DailyDevTips1" rel="me">Twitter</a>
あなたのウェブサイトのドメインをTwitterのプロファイルに含まれていることを確認します.手順2。ウェブリンクコレクションの追加
一度、我々は我々のドメインに我々の2つの関連を加える必要があります
<link rel="webmention" href="https://webmention.io/{username}/webmention" />
<link rel="pingback" href="https://webmention.io/{username}/xmlrpc" />
{username}
などの実際のドメインに置き換えます.ステップ3。接続としてつぶやきを接続する
それで、今、我々はウェブ言及を受けることができます、しかし、すべての正直で、WHOはWebReferenceを我々に送りますか?
人々のウェブサイトに私たちのURLをつぶやき変換しましょう!
我々は、bridgyのようなホストサービスを使用することができます.
ちょうどTwitterのアイコンをクリックしてログインします.
その後、あなたのウェブサイトや世論調査のTwitterをクロールすることができます.
Bridgy only gets the most recent Tweets, but you can add a Tweet URL in the Resend for the post button.
実際のウェブサイトでの応答は以下のようになります.
ステップ4。すべてのウェブページを取得する関数
すべての設定を持っているので、WebReadingのためのすべてのウェブメンテーションズを集めます.入出力API.
では、カスタムデータファイルを
daily-dev-tips.com
フォルダに追加できます.それを
_data
と呼びましょうconst fs = require('fs');
const fetch = require('node-fetch');
const unionBy = require('lodash/unionBy');
const domain = 'daily-dev-tips.com';
// Load .env variables with dotenv
require('dotenv').config();
// Define Cache Location and API Endpoint
const CACHE_DIR = '_cache';
const API = 'https://webmention.io/api';
const TOKEN = process.env.WEBMENTION_IO_TOKEN;
async function fetchWebmentions(since, perPage = 10000) {
if (!domain) {
// If we dont have a domain name, abort
console.warn('>>> unable to fetch webmentions: no domain name specified in site.json');
return false;
}
if (!TOKEN) {
// If we dont have a domain access token, abort
console.warn('>>> unable to fetch webmentions: no access token specified in environment.');
return false;
}
let url = `${API}/mentions.jf2?domain=${domain}&token=${TOKEN}&per-page=${perPage}`;
if (since) url += `&since=${since}`;
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 filePath = `${CACHE_DIR}/webmentions.json`;
const fileContent = JSON.stringify(data, null, 2);
// create cache folder if it doesnt exist already
if (!fs.existsSync(CACHE_DIR)) {
fs.mkdirSync(CACHE_DIR);
}
// write data to cache json file
fs.writeFile(filePath, fileContent, err => {
if (err) throw err;
console.log(`>>> webmentions cached to ${filePath}`);
})
}
// get cache contents from json file
function readFromCache() {
const filePath = `${CACHE_DIR}/webmentions.json`;
if (fs.existsSync(filePath)) {
const cacheFile = fs.readFileSync(filePath);
const cachedWebmentions = JSON.parse(cacheFile);
// merge cache with wms for legacy domain
return {
lastFetched: cachedWebmentions.lastFetched,
children: cachedWebmentions.children
};
}
// no cache found.
return {
lastFetched: null,
children: {}
};
}
module.exports = async function () {
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') {
const feed = await fetchWebmentions(cache.lastFetched);
if (feed) {
const webmentions = {
lastFetched: new Date().toISOString(),
children: mergeWebmentions(cache, feed)
}
writeToCache(webmentions);
return webmentions;
}
}
return cache;
}
大規模なファイルですが、基本的には、エンドポイント用のWebを読みます.https://webmention.io/api/mentions.jf2?domain=${domain}&token=${TOKEN}
その後、キャッシュファイルでマージします.この関数は、私たちの11回目のブログを構築したら実行されます.
To make it realtime, we can leverage other endpoints, but I won't go into that. Find more on Shawn's blog
このデータファイルを作成することで、
webmentions.js
という変数にアクセスできます.ステップ5。ブログの表示の表示
前述のように、我々は現在
{{ webmentions }}
変数を持ちます.そして、私の場合は、次の要素をウェブサイトから分割します.
ブログページのレイアウトで次のように追加します.
// layouts/post.njk
{% include "partials/components/webmentions.njk" %}
このwebファイルでは、すべての言及をロードします.まず、現在のページの完全なURLを取得する必要があります.
{% set currentUrl %}{{ site.url + page.url | uniUrlFilter }}{% endset %}
私はUniurlFilterを作成しました、私は私のURLのmodule.exports = function uniUrlFilter(value) {
return encodeURI(value);
};
次に、この特定のURLのWebページを取得する必要があります.{%- set mentions = webmentions.children | getWebmentionsForUrl(currentUrl) -%}
そして、このフィルタはそれらをきちんとした配列にソートします.const sanitizeHTML = require('sanitize-html');
module.exports = function getWebmentionsForUrl(webmentions, url) {
const likes = ['like-of'];
const retweet = ['repost-of'];
const messages = ['mention-of', 'in-reply-to'];
const hasRequiredFields = entry => {
const { author, published, content } = entry;
return author.name && published && content;
};
const sanitize = entry => {
const { content } = entry;
if (content['content-type'] === 'text/html') {
content.value = sanitizeHTML(content.value);
}
return entry;
};
return {
'likes': webmentions
.filter(entry => entry['wm-target'] === url)
.filter(entry => likes.includes(entry['wm-property'])),
'retweet': webmentions
.filter(entry => entry['wm-target'] === url)
.filter(entry => retweet.includes(entry['wm-property']))
.filter(hasRequiredFields)
.map(sanitize),
'messages': webmentions
.filter(entry => entry['wm-target'] === url)
.filter(entry => messages.includes(entry['wm-property']))
.filter(hasRequiredFields)
.map(sanitize)
};
}
見ることができるように、私はピースごとにソートするWebCountriesの3つの異なる要素をフィルタリングします.我々は、それから部分的に我々の
{{ webmentions }}
部分で彼らをループさせることができます.<ol>
{% for webmention in mentions.likes %}
<li class="webmentions__item">
<a {% if webmention.url %}href="{{ webmention.url }}"{% endif %} target="_blank" rel="noopener noreferrer" title="{{ webmention.author.name }}">
{% if webmention.author.photo %}
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy">
{% else %}
<img src="{{ '/assets/images/avatar-default.jpg' | url }}" alt="" width="48" height="48">
{% endif %}
</a>
</li>
{% endfor %}
</ol>
<ol>
{% for webmention in mentions.retweets %}
<li class="webmentions__item">
<a {% if webmention.url %}href="{{ webmention.url }}"{% endif %} target="_blank" rel="noopener noreferrer" title="{{ webmention.author.name }}">
{% if webmention.author.photo %}
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy">
{% else %}
<img src="{{ '/assets/images/avatar-default.jpg' | url }}" alt="" width="48" height="48">
{% endif %}
</a>
</li>
{% endfor %}
</ol>
<ol>
{% for webmention in mentions.messages %}
<li class="webmentions__item">
<a {% if webmention.url %}href="{{ webmention.url }}"{% endif %} target="_blank" rel="noopener noreferrer" title="{{ webmention.author.name }}">
{% if webmention.author.photo %}
<img src="{{ webmention.author.photo }}" alt="{{ webmention.author.name }}" width="48" height="48" loading="lazy">
{% else %}
<img src="{{ '/assets/images/avatar-default.jpg' | url }}" alt="" width="48" height="48">
{% endif %}
</a>
<strong>{{ webmention.author.name }}</strong>
<time class="dt-published" datetime="{{ webmention.published | w3DateFilter }}">
{{ webmention.published | dateFilter }}
</time>
{{ webmention.content.html | safe }}
</li>
{% endfor %}
</ol>
彼らは私たちは、ちょうどいくつかのスタイリングを追加し、あなたのEustenmentブログのショーケースのウェブサイトにあなたの準備ができています.読んでいただきありがとうございます、接続しましょう!
私のブログを読んでくれてありがとう.私の電子メール会報を購読して、Facebook
Reference
この問題について(11 tyブログにおけるウェブメンテーションの実装), 我々は、より多くの情報をここで見つけました https://dev.to/dailydevtips1/implementing-webmentions-on-a-11ty-blog-5bhgテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol