summaryrefslogtreecommitdiff
path: root/data/webmentions.json
diff options
context:
space:
mode:
authorforgejo-actions <forgejo-actions@eltr.ac>2026-03-13 17:02:01 +0000
committerforgejo-actions <forgejo-actions@eltr.ac>2026-03-13 17:02:01 +0000
commitc8fefa2e1f63afc91dcc4bda0d530e99d27cf3fe (patch)
tree669d66eebc08e58d90db923eb4dd3edd9ad5050a /data/webmentions.json
parentc7aaf0cda9bfdb4adc637baf4c4479e784bc5361 (diff)
chore: update webmentions
Diffstat (limited to 'data/webmentions.json')
-rw-r--r--data/webmentions.json290
1 files changed, 210 insertions, 80 deletions
diff --git a/data/webmentions.json b/data/webmentions.json
index e93e9063..c22b5d0f 100644
--- a/data/webmentions.json
+++ b/data/webmentions.json
@@ -67,6 +67,136 @@
"source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DaiPRN56VFn0HeBU",
"type": "in-reply-to",
"url": "https://c7.io/@LeeHenry/116222476038507206"
+ },
+ {
+ "author": {
+ "name": "Eltrac :neocat_laptop:",
+ "photo": "https://avatars.webmention.io/akk-media.eltr.ac/96fdded4db077fd77188a2ca1427f357b0fda90f141c58c9bac3e1706c050c2a.jpg",
+ "type": "card",
+ "url": "https://akk.eltr.ac/users/eltrac"
+ },
+ "content": {
+ "html": "\u003cp\u003eNeocities 上确实用得会更多一些,毕竟那边自带复古 Web 文化氛围;\u003ca href=\"https://indieweb.org/\"\u003eIndieWeb\u003c/a\u003e 也有不少。不过总体而言有 88x31 图标的个人网站确实不多,国外的独立网站会多一些,中文互联网基本没有。\u003c/p\u003e\u003cp\u003e和 Y2K 风格不是直接绑定的,虽然有些复古气息,但喜欢的话都可以做,可以看\u003ca href=\"https://88x31.nl/\"\u003e这里\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e其实随便翻到某个 \u003ca href=\"https://en.wikipedia.org/wiki/Web_badge\"\u003eWikipedia 条目\u003c/a\u003e的右下角就能看到两个 88x31 按钮,不过是用来表示组织的,而不是个人。\u003c/p\u003e\n\u003ca href=\"https://indieweb.org/\"\u003eIndieWeb\u003c/a\u003e",
+ "text": "Neocities 上确实用得会更多一些,毕竟那边自带复古 Web 文化氛围;IndieWeb 也有不少。不过总体而言有 88x31 图标的个人网站确实不多,国外的独立网站会多一些,中文互联网基本没有。\n\n和 Y2K 风格不是直接绑定的,虽然有些复古气息,但喜欢的话都可以做,可以看这里。\n\n其实随便翻到某个 Wikipedia 条目的右下角就能看到两个 88x31 按钮,不过是用来表示组织的,而不是个人。\nIndieWeb"
+ },
+ "published": "2026-03-13T15:19:29+00:00",
+ "received": "2026-03-13T16:44:14Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4Dc5VutGl1SUOfigi",
+ "type": "in-reply-to",
+ "url": "https://akk.eltr.ac/notice/B4Dc5VutGl1SUOfigi"
+ },
+ {
+ "author": {
+ "name": "Cytrogen",
+ "photo": "https://avatars.webmention.io/media.otter.homes/310ced382f23dbe7131a3693f6c23b83c4c4a8ff66b84ce6494cc51720597349.jpg",
+ "type": "card",
+ "url": "https://m.otter.homes/@Cytrogen"
+ },
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://c7.io/@LeeHenry\" class=\"u-url\"\u003e@\u003cspan\u003eLeeHenry\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 需要在「发布默认值」设置里自行开启,除了 Markdown 还有 HTML 支持。\u003c/p\u003e\u003cp\u003e又看了一眼发现我这边显示是 glitch-soc 的功能,貌似是 Mastodon 的一个 fork。\u003c/p\u003e",
+ "text": "@LeeHenry 需要在「发布默认值」设置里自行开启,除了 Markdown 还有 HTML 支持。\n\n又看了一眼发现我这边显示是 glitch-soc 的功能,貌似是 Mastodon 的一个 fork。"
+ },
+ "published": "2026-03-13T16:03:07+00:00",
+ "received": "2026-03-13T16:44:37Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DfzIjBn83JfFUYDo",
+ "type": "in-reply-to",
+ "url": "https://m.otter.homes/@Cytrogen/116222708134251075"
+ },
+ {
+ "author": {
+ "name": "Eltrac :neocat_laptop:",
+ "photo": "https://avatars.webmention.io/akk-media.eltr.ac/96fdded4db077fd77188a2ca1427f357b0fda90f141c58c9bac3e1706c050c2a.jpg",
+ "type": "card",
+ "url": "https://akk.eltr.ac/users/eltrac"
+ },
+ "content": {
+ "html": "\u003cp\u003eMastodon 似乎是不支持 Markdown 语法的,但是能够渲染来自其他联邦宇宙软件的 Markdown,比如 Misskey、Pleroma 和 Akkoma 就支持 Markdown,Mastodon 有一些分支也支持。\u003c/p\u003e\u003cp\u003e\u003ca href=\"http://c7.io\"\u003ec7.io\u003c/a\u003e 的 Mastodon 版本是不支持的。如果想用 Markdown 的话可以换一个实例,或者自建实例。\u003c/p\u003e\u003cp\u003eMastodon 还不支持表情回应,导致我每次发表情回应之前都要思考一下对方的实例支不支持。 \u003cimg alt=\"ablobcatcoffee\" src=\"https://akk.eltr.ac/emoji/blobcat/ablobcatcoffee.png\" /\u003e\u003c/p\u003e",
+ "text": "Mastodon 似乎是不支持 Markdown 语法的,但是能够渲染来自其他联邦宇宙软件的 Markdown,比如 Misskey、Pleroma 和 Akkoma 就支持 Markdown,Mastodon 有一些分支也支持。\n\nc7.io 的 Mastodon 版本是不支持的。如果想用 Markdown 的话可以换一个实例,或者自建实例。\n\nMastodon 还不支持表情回应,导致我每次发表情回应之前都要思考一下对方的实例支不支持。"
+ },
+ "published": "2026-03-13T16:09:28+00:00",
+ "received": "2026-03-13T16:44:39Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DgY300GLN519vOTo",
+ "type": "in-reply-to",
+ "url": "https://akk.eltr.ac/notice/B4DgY300GLN519vOTo"
+ },
+ {
+ "author": {
+ "name": "KIP/JΛYCHØU ⁂ :neocat_cofe:",
+ "photo": "https://avatars.webmention.io/files.mstdn.feddit.social/b3a5ebdc7764c92d0a28a39ee05451f98685bd5f10185dc981856443952aa13c.png",
+ "type": "card",
+ "url": "https://mstdn.feddit.social/@admin"
+ },
+ "content": null,
+ "published": null,
+ "received": "2026-03-13T16:44:40Z",
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B2SrMy0eBj7rdlvD3A",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B4DWqQ1MPJr65cgHQ0#favorited-by-B2SrMy0eBj7rdlvD3A"
+ },
+ {
+ "author": {
+ "name": "lok :l3:",
+ "photo": "https://rex.cat/fileserver/01QQK4FHH1T4CDKX7SYB35KPSF/attachment/original/01KAMR51B7SVYB32S0BK85NQ7M.png",
+ "type": "card",
+ "url": "https://rex.cat/@lok"
+ },
+ "content": null,
+ "published": null,
+ "received": "2026-03-13T16:45:29Z",
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B2SrMficC20SudLYRc",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B4DWqQ1MPJr65cgHQ0#favorited-by-B2SrMficC20SudLYRc"
+ },
+ {
+ "author": {
+ "name": "伏枥 :ablobcatsnowjoy:",
+ "photo": "https://avatars.webmention.io/c7.io/3b024daedc46bd2daab952cc2c59cc2fd62b234725ef25e1edd9a6cfe1106bda.jpg",
+ "type": "card",
+ "url": "https://c7.io/@LeeHenry"
+ },
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e \u003cbr /\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://m.otter.homes/@Cytrogen\" class=\"u-url\"\u003e@\u003cspan\u003eCytrogen\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e \u003c/p\u003e\u003cp\u003e感谢回答!我研究一下 \u003cimg alt=\"blobcatcoffee\" src=\"https://c7.io/system/custom_emojis/images/000/027/428/original/5bb7e84c5678caab.png\" /\u003e\u003c/p\u003e",
+ "text": "@eltrac \n@Cytrogen \n\n感谢回答!我研究一下"
+ },
+ "published": "2026-03-13T16:24:33+00:00",
+ "received": "2026-03-13T17:00:17Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DhtXUoAfV7da956W",
+ "type": "in-reply-to",
+ "url": "https://c7.io/@LeeHenry/116222792371338009"
+ },
+ {
+ "author": {
+ "name": "lok :l3:",
+ "photo": "https://rex.cat/fileserver/01QQK4FHH1T4CDKX7SYB35KPSF/attachment/original/01KAMR51B7SVYB32S0BK85NQ7M.png",
+ "type": "card",
+ "url": "https://rex.cat/@lok"
+ },
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 哇哇哇好看耶,可以放在我的网站上吗 \u003cimg alt=\"happy\" src=\"https://rex.cat/fileserver/01RE9Y7N8ZQW9T8ZFBJRCNB38F/emoji/original/01KERSRBGVZQ4SN7R3RTRPYFAG.gif\" /\u003e\u003c/p\u003e",
+ "text": "@eltrac 哇哇哇好看耶,可以放在我的网站上吗"
+ },
+ "published": "2026-03-13T16:30:57+00:00",
+ "received": "2026-03-13T16:44:08Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DiT1KFG0FkHu7i4m",
+ "type": "in-reply-to",
+ "url": "https://rex.cat/@lok/statuses/01KKM0JVDZWMGRTVNC31VYS50M"
+ },
+ {
+ "author": {
+ "name": "Eltrac :neocat_laptop:",
+ "photo": "https://avatars.webmention.io/akk-media.eltr.ac/96fdded4db077fd77188a2ca1427f357b0fda90f141c58c9bac3e1706c050c2a.jpg",
+ "type": "card",
+ "url": "https://akk.eltr.ac/users/eltrac"
+ },
+ "content": {
+ "html": "\u003cp\u003e可以啊,如果可以交换的话就更好了 uwu\u003c/p\u003e",
+ "text": "可以啊,如果可以交换的话就更好了 uwu"
+ },
+ "published": "2026-03-13T16:32:19+00:00",
+ "received": "2026-03-13T16:44:08Z",
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B4DWqQ1MPJr65cgHQ0/B4DiaUaupnh75gU3qC",
+ "type": "in-reply-to",
+ "url": "https://akk.eltr.ac/notice/B4DiaUaupnh75gU3qC"
}
],
"/about/": [
@@ -336,6 +466,37 @@
},
{
"author": {
+ "name": "花島Saki",
+ "photo": "https://avatars.webmention.io/files.mstdn.party/f114ba351fb35db23831a3d172a154cc85b008d835c950009a711c648d3e5679.jpg",
+ "type": "card",
+ "url": "https://mstdn.party/@hanajima_saki"
+ },
+ "content": null,
+ "published": null,
+ "received": "2026-03-10T16:59:10Z",
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B3bjSNrhW69SacjQdk",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B47Na8WhcQVAf7k6bI#favorited-by-B3bjSNrhW69SacjQdk"
+ },
+ {
+ "author": {
+ "name": "Spike Leung",
+ "photo": "https://avatars.webmention.io/taxodium.ink/2b954e9d7ff8da1cb55e49fc098ea06f464c9ffd1872e1f92cc2ac1bb10ad7c4.png",
+ "type": "card",
+ "url": "https://taxodium.ink"
+ },
+ "content": {
+ "html": "\u003ch1 class=\"p-name\"\u003e给博客添加 Webmention\u003c/h1\u003e\n\u003ch2\u003e目录\u003c/h2\u003e\n\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D459C268-A454-4D43-9E49-97D0A90C2F67\"\u003e什么是 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#E55EE851-CF6C-4FC6-A4F8-94FD38BFA17F\"\u003e为什么接入 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D55D3AFA-42A0-4D14-A52F-FB34162E31DD\"\u003e如何接入 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D2EB3BEC-396F-43D6-BA15-A89E38A671F8\"\u003e一些问题\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#967313DB-C374-4182-8F81-AE96666BF2CD\"\u003e写在最后\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#806C5BB0-D8CB-4AD8-BC52-2866C9072B41\"\u003e其他参考文章\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\n???? The Great Escape Of Our Time - 椅子乐团 The Chairs\n\u003c/p\u003e\n\n\u003ch2\u003e什么是 Webmention\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\nWebmention 是一种通知,表明一个 URL 链接到另一个 URL。\n\u003c/p\u003e\n\n\u003cp\u003e\n例如,Alice 在她的博客上写了一篇有趣的帖子。随后 Bob 在自己的网站上写了一篇回复她的帖子,并链接回 Alice 的原始帖子。\nBob 的发布软件向 Alice 发送一个 Webmention,通知她的文章被回复了,\nAlice 的软件可以将该回复显示为原始帖子上的评论。\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://www.w3.org/TR/webmention/#introduction-p-1:~:text=A%20Webmention%20is,the%20original%20post.\"\u003eSource\u003c/a\u003e\n\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003cp\u003e\nWebmention 和评论差不多,只是它的门槛相对高一点,需要你写一篇文章,并链接到你想评论的文章。\n(或者在社交媒体如 BlueSky、Mastodon 上发一个帖子,引用文章的链接)\n\u003c/p\u003e\n\n\u003cp\u003e\n如果对方支持了 Webmention,你发送 Webmention 通知后,对方就会将你的内容显示出来。\n\u003c/p\u003e\n\nWebmention 的大致流程\u003ca href=\"https://taxodium.ink/images/add-webmention-to-blog/mermaid.png\"\u003e\u003cimg src=\"https://taxodium.ink/images/add-webmention-to-blog/mermaid.png\" alt=\"mermaid.png\" /\u003e\u003c/a\u003e\n\n\u003cspan\u003e图1 \u003c/span\u003eWebmention 的大致流程,参考 \u003ca href=\"https://www.w3.org/TR/webmention/#protocol-summary\"\u003ehttps://www.w3.org/TR/webmention/#protocol-summary\u003c/a\u003e\n\n\n\u003ch2\u003e为什么接入 Webmention\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\n\u003cb\u003e实现跨站点的对话。\u003c/b\u003e当你链接到某个网站时,你可以发送一个 Webmention 来通知它。如果该网站支持 Webmention,那么该网站可能会将你的帖子显示为评论、赞或其他回应,就这样,你就实现了从一个站点到另一个站点的对话!\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://indieweb.org/Webmention#:~:text=Enables%20cross-site%20conversations.%20When%20you%20link%20to%20a%20website%2C%20you%20can%20send%20it%20a%20Webmention%20to%20notify%20it.%20If%20it%20supports%20Webmentions%2C%20then%20that%20website%20may%20display%20your%20post%20as%20a%20comment%2C%20like%2C%20or%20other%20response%2C%20and%20presto%2C%20you%E2%80%99re%20having%20a%20conversation%20from%20one%20site%20to%20another!\"\u003eSource\u003c/a\u003e\n\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003cp\u003e\n我觉得 Webmention 和集成在博客中的评论系统是类似的。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你要回应一篇文章,通过 Webmention,你需要写一篇文章链接到这篇文章,并发送一个 Webmention 通知。通过如 \u003ca href=\"https://brid.gy/\"\u003eBridgy\u003c/a\u003e 之类的服务,也可以收集社交网络上(Blusky、Mastodon 等)关于文章的回应,例如点赞、转发等。\n\u003c/p\u003e\n\n\u003cp\u003e\n但我觉得并没有比集成于博客的评论系统更方便。\n\u003c/p\u003e\n\n\u003cp\u003e\n从数据层面看,除非自己买服务器搭建 Webmention,否则用第三方提供的服务,数据依然不在自己的手上。\n\u003c/p\u003e\n\n\u003cp\u003e\n所以我为什么要接入 Webmention?\n\u003c/p\u003e\n\n\u003cp\u003e\n最开始是在 \u003ca href=\"https://www.owenyoung.com/blog/de-roboticization/#2-xie-bo-ke%20:~:text=%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E6%B2%A1%E6%9C%89%E8%AF%84%E8%AE%BA%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%AF%84%E8%AE%BA%E5%8A%9F%E8%83%BD%E4%BC%9A%E5%85%B6%E5%AE%9E%E4%BC%9A%E8%AE%A9%E6%88%91%E5%BC%95%E5%85%A5%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%9A%84%E5%8C%85%E8%A2%B1%E6%84%9F%E3%80%82%E6%88%91%E8%A7%89%E5%BE%97%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E7%9A%84%E5%A5%BD%E5%8A%9E%E6%B3%95%E6%98%AF%E5%BC%95%E5%85%A5webmention%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E4%BA%BA%E6%83%B3%E8%A6%81%E5%9B%9E%E5%BA%94%EF%BC%8C%E5%BE%97%E6%8F%90%E4%BA%A4%E8%87%AA%E5%B7%B1%E7%9A%84%E5%9B%9E%E5%BA%94%E7%BD%91%E5%9D%80%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E8%AF%84%E8%AE%BA%E6%A1%86%E9%87%8C%E7%95%99%E4%B8%8B%E4%B8%89%E8%A8%80%E4%B8%A4%E8%AF%AD%E3%80%82%E8%BF%99%E6%8F%90%E9%AB%98%E4%BA%86%E8%AF%84%E8%AE%BA%E7%9A%84%E6%88%90%E6%9C%AC%EF%BC%8C%E9%BC%93%E5%8A%B1%E6%83%B3%E8%A6%81%E7%95%99%E8%A8%80%E7%9A%84%E4%BA%BA%E6%8B%A5%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E5%8D%9A%E5%AE%A2%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%86%99%E4%B8%80%E4%BA%9B%E7%BB%8F%E8%BF%87%E6%80%9D%E8%80%83%E7%9A%84%E8%AF%9D%E8%AF%AD%E3%80%82%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E5%B7%B2%E7%BB%8F%E6%94%AF%E6%8C%81%E4%BA%86%20Webmention%EF%BC%8C%E6%88%91%E5%9C%A8Now%2C%20I%E2%80%99m%20in%20IndieWeb%3F%E9%87%8C%E6%9C%89%E8%AE%B0%E5%BD%95%E6%88%91%E7%9A%84%E5%AE%9E%E7%8E%B0%E3%80%82\"\u003e我想让自己说话不那么“端着” | Owen Young\u003c/a\u003e 中了解到 Webmention,当时觉得有些麻烦。\n\u003c/p\u003e\n\n\u003cp\u003e\n最近网上冲浪的时候,看到不少博客都有集成 Webmention,然后了解了一下 \u003ca href=\"https://webmention.io/\"\u003ewebmention.io\u003c/a\u003e 的使用,看起来不麻烦,就想着集成看看。\n\u003c/p\u003e\n\n\u003cp\u003e\n非要找个理由的话,就是折腾一下,好玩吧。\n\u003c/p\u003e\n\n\n\n\u003ch2\u003e如何接入 Webmention\u003c/h2\u003e\n\u003cp\u003e\n如果自己搭建的话,可以参照 \u003ca href=\"https://www.w3.org/TR/webmention\"\u003eWebmention 规范\u003c/a\u003e 实现;或者找现成的工具,你可以在 \u003ca href=\"https://indieweb.org/Webmention\"\u003eWebmention | IndieWeb\u003c/a\u003e 找到很多工具和服务。\n\u003c/p\u003e\n\n\u003cp\u003e\n我目前实现很简单,接收依赖 webmention.io 提供的服务,需要自己编写一点 \u003ca href=\"https://taxodium.ink/js/webmention.js\"\u003e脚本\u003c/a\u003e 调用 API;发送通过手动触发;麻烦一些的地方是给博客添加 \u003ca href=\"https://microformats.org/wiki/Main_Page\"\u003emicroformats\u003c/a\u003e 。\n\u003c/p\u003e\n\n\n\u003ch3\u003e作为接收方\u003c/h3\u003e\n\u003cp\u003e\n接收我使用 webmention.io 提供的服务,按照 \u003ca href=\"https://indielogin.com/setup\"\u003eHow to Set Up Your Website for IndieLogin.com\u003c/a\u003e 的说明进行设置。\n\u003c/p\u003e\n\n\u003cp\u003e\n我用 GitHub 进行验证,需要在 GitHub Profile 中包含我的网站,同时在网站添加一个链接。\n\u003c/p\u003e\n\n\n\u003ca href=\"https://taxodium.ink/images/add-webmention-to-blog/github-profile.png\"\u003e\u003cimg src=\"https://taxodium.ink/images/add-webmention-to-blog/github-profile.png\" alt=\"github-profile.png\" /\u003e\u003c/a\u003e\n\n\u003cspan\u003e图2 \u003c/span\u003e我的 GitHub Profile 页面,我把网站的地址添加到了 Profile 中\n\u003cpre\u003e\u003ccode\u003e\u0026lt;\u003cspan\u003ehead\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e省略其他内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003elink\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://github.com/spike-leung\"\u003c/span\u003e \u003cspan\u003erel\u003c/span\u003e=\u003cspan\u003e\"me\"\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e省略其他内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n\u0026lt;/\u003cspan\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\n\n\u003cp\u003e\n这样就能通过 webmention.io 的验证了。\n\u003c/p\u003e\n\n\u003cp\u003e\n接下来按照 webmention.io 提供的 API 获取 Webmentions 的数量和内容,需要在页面上添加 HTML 元素,写 \u003ca href=\"https://taxodium.ink/js/webmention.js\"\u003e一些 JS 代码\u003c/a\u003e 调用 API 渲染数据(也可以用 \u003ca href=\"https://github.com/PlaidWeb/webmention.js\"\u003ewebmention.js\u003c/a\u003e),再写点 CSS 优化一下样式。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你打算渲染 Webmentions 返回的 HTML,需要注意 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS\"\u003eCross-site scripting (XSS)\u003c/a\u003e 攻击。\n\u003c/p\u003e\n\n防止 XSS 攻击\u003cp\u003e\n防止 XSS 攻击,\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types\"\u003eTrusted Types API\u003c/a\u003e 看起来不错,可惜浏览器支持度不够。\n\u003c/p\u003e\n\n\u003cp\u003e\n防御 XSS 主要从两方面入手:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e净化 (sanitize) 用户输入的内容。可以使用 \u003ca href=\"https://github.com/cure53/DOMPurify\"\u003eDOMPurify\u003c/a\u003e 处理。\u003c/li\u003e\n\u003cli\u003e使用 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP\"\u003eContent Security Policy (CSP)\u003c/a\u003e 限制执行。\u003ca href=\"https://www.netlify.com/blog/general-availability-content-security-policy-csp-nonce-integration/\"\u003eNetlify 有插件支持\u003c/a\u003e,倒是方便了许多。要注意的是,当开启了 CSP,一些行内的脚本,如写在元素上的 onclick、 onchange 等会被阻止执行,需要将他们挪动到 JS 文件里。\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n也可以期待一下 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Element/setHTML\"\u003eElement: setHTML() method\u003c/a\u003e 被广泛支持,它提供了一种 XSS 安全的方法用于插入 HTML 内容到页面中。\n\u003c/p\u003e\n\u003cp\u003e\n搭建好之后,可以用 \u003ca href=\"https://webmention.rocks/#:~:text=Testing%20your%20Receiver\"\u003eWebmention Rocks!\u003c/a\u003e 提供的服务进行测试。\n\u003c/p\u003e\n\n\u003cp\u003e\n至于查看 Webmentions 也有几种方法:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e到对应的页面下看\u003c/li\u003e\n\u003cli\u003e订阅 webmention.io 提供的 \u003ca href=\"https://webmention.io/settings\"\u003eMentions Feed\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e使用 webmention.io 提供的 \u003ca href=\"https://webmention.io/settings/webhooks\"\u003eWeb Hook\u003c/a\u003e 通知自己\u003c/li\u003e\n\u003cli\u003e到 webmention.io 的 \u003ca href=\"https://webmention.io/dashboard\"\u003eDashbaord\u003c/a\u003e 查看\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003e作为发送方\u003c/h3\u003e\n\u003cp\u003e\n作为发送方,你只需要在你的文章中包含对方的链接,就可以向对方发送 Webmention 了。\n\u003c/p\u003e\n\n\u003cp\u003e\n但是如果你想让你发送的内容更丰富一些,就需要通过 \u003ca href=\"https://microformats.org/wiki/Main_Page\"\u003emicroformats\u003c/a\u003e 标记网站信息,如用户名、头像、内容、你要提及的链接等,从而让 Webmention 解析展示。\n\u003c/p\u003e\n\n\u003cp\u003e\n按理说只要包含了对方链接,对方就能收到 Webmention。\n\u003c/p\u003e\n\n\u003cp\u003e\n但我发送后却收到了「The Microformats at the source URL do not contain a link to the target URL.」的错误提示。\n\u003c/p\u003e\n\n\u003cp\u003e\n可能是因为我使用 microformats 标记了内容,此时需要确保 microformats 解析后的内容中,包含对方的 URL。\n\u003c/p\u003e\n\u003cp\u003e\n最主要的标记是 \u003ca href=\"https://microformats.org/wiki/h-card\"\u003eh-card\u003c/a\u003e 和 \u003ca href=\"https://microformats.org/wiki/h-entry\"\u003eh-entry\u003c/a\u003e,h-card 标记\u003cem\u003e用户\u003c/em\u003e信息;\nh-entry 标记\u003cem\u003e内容\u003c/em\u003e信息,标记的部分会作为 Webmention 的内容呈现。\n\u003c/p\u003e\n\n\u003cp\u003e\n关于 h-card 和 h-entry 的作用,推荐看 \u003ca href=\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003eSending your First Webmention from Scratch\u003c/a\u003e,文章循序渐进地引导你添加相应的标记,并且有对应的示例,同时文章本身也可以用来测试 Webmention 的发送。\n\u003c/p\u003e\n\n\u003cp\u003e\nmicroformats 这些标记,可以和 HTML 做类比,它也是有层级关系的,最终会解析成一个 JSON 的树形结构。在你测试的时候,可以从 \u003ca href=\"https://microformats.org/wiki/parsers\"\u003eMicroformats Parsers\u003c/a\u003e 找一个 parser 检查你的文章解析出来的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003cb\u003e关于 h-entry\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=the%20%22datetime%22%20property.-,what%20is%20the%20bare%20minimum%20list%20of%20required%20properties%20on%20an,a%20nested%20h-card%20with%20author%20details%20like%20name%2C%20photo%2C%20url.,-Examples%20in%20the\"\u003ewhat is the bare minimum list of required properties on an h-entry\u003c/a\u003e 中回答道,没有任何 h-entry 的属性是强制要求的。\n\u003c/p\u003e\n\n\u003cp\u003e\n但推荐至少包含:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=e-content%20-%20full%20content%20of%20the%20entry\"\u003ee-content\u003c/a\u003e 标记文章内容,被标记的内容会作为 Webmention 的内容被发送\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=p-name%20-%20entry%20name/title\"\u003ep-name\u003c/a\u003e 标记文章标题\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=p-author%20-%20who%20wrote%20the%20entry%2C%20optionally%20embedded%20h-card(s)\"\u003ep-author\u003c/a\u003e 标记作者信息,一般会和 h-card 结合使用\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n一些我建议加上的:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-in-reply-to%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20reply%20to%20(i.e.%20doesn%E2%80%99t%20make%20sense%20without%20context%2C%20could%20show%20up%20in%20comment%20thread)%2C%20optionally%20an%20embedded%20h-cite%20(reply-context)%20(example)\"\u003eu-in-reply-to\u003c/a\u003e 标记你回应的链接。此外 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-like-of%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20a%20%E2%80%9Clike%E2%80%9D%20(favorite%2C%20star)%20of.%20Optionally%20an%20embedded%20h-cite\"\u003eu-like-of\u003c/a\u003e、\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-repost-of%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20a%20%E2%80%9Crepost%E2%80%9D%20of.%20Optionally%20an%20embedded%20h-cite\"\u003eu-report-of\u003c/a\u003e 等可以用于标记不同的引用目的\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=dt-published%20-%20when%20the%20entry%20was%20published\"\u003edt-published\u003c/a\u003e 标记文章的发布日期\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=dt-updated%20-%20when%20the%20entry%20was%20updated\"\u003edt-updated\u003c/a\u003e 标记文章的更新日期\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n\u003cb\u003e关于 h-card\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\nh-card 是用来标记用户信息的,介绍一些我觉得比较有用的:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=p-name%20-%20The%20full/formatted%20name%20of%20the%20person%20or%20organization\"\u003ep-name\u003c/a\u003e 标记个人或组织的全称\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-email%20-%20email%20address\"\u003eu-email\u003c/a\u003e 标记邮箱,一般标记在 mailto 链接上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-logo%20-%20a%20logo%20representing%20the%20person%20or%20organization%20(e.g.%20a%20face%20icon)\"\u003eu-logo\u003c/a\u003e 标记你的 logo,一般标记在 \u003ccode\u003e\u0026lt;img\u0026gt;\u003c/code\u003e 标签上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-photo%20-%20a%20photo%20of%20the%20person%20or%20organization\"\u003eu-photo\u003c/a\u003e 标记你的头像,一般标记在 \u003ccode\u003e\u0026lt;img\u0026gt;\u003c/code\u003e 标签上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-url%20-%20home%20page%20or%20other%20URL%20representing%20the%20person%20or%20organization\"\u003eu-url\u003c/a\u003e 标记你的主页,一般标记在一个链接上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=p-note%20-%20additional%20notes\"\u003ep-note\u003c/a\u003e 标记额外信息,有人会用来写自我介绍\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n除了这些,还有标记地址、性别、国籍、出生日期、工作等,感兴趣可以自行探索。\n\u003c/p\u003e\n\n\u003cp\u003e\nh-card 可以结合 h-entry 的 p-author 用于标记文章的作者信息,\u003cb\u003e在这种场景下,h-entry 需要是 h-card 的父元素。\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n综上,一个相对完整的 microformats 标记是这样的:\n\u003c/p\u003e\n\n\n\u003cpre\u003e\u003ccode\u003e\u0026lt;\u003cspan\u003e!doctype\u003c/span\u003e html\u0026gt;\n\u0026lt;\u003cspan\u003emeta\u003c/span\u003e \u003cspan\u003echarset\u003c/span\u003e=\u003cspan\u003e\"utf-8\"\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan\u003etitle\u003c/span\u003e\u0026gt;\u003cspan\u003e\u003cspan\u003eHello World\u003c/span\u003e\u003c/span\u003e\u0026lt;/\u003cspan\u003etitle\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan\u003ebody\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ediv\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"h-entry\"\u003c/span\u003e\u0026gt; \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e注意 h-entry 是其他属性的父元素,包含了 h-card\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ediv\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"p-author h-card\"\u003c/span\u003e\u0026gt; \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e使用 h-card 结合 p-author 标记作者信息\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003eimg\u003c/span\u003e \u003cspan\u003esrc\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/images/aaronpk.jpg\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-photo\"\u003c/span\u003e \u003cspan\u003ewidth\u003c/span\u003e=\u003cspan\u003e\"40\"\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-url p-name\"\u003c/span\u003e\u0026gt;Aaron Parecki\u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ediv\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记引用的链接,表示回复\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e\u0026gt;in reply to: \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-in-reply-to\"\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003c/span\u003e\u0026gt;@aaronpk\u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记回复的内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"e-content\"\u003c/span\u003e\u0026gt;Trying out this guide to sending webmentions\u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记当前文章的 URL\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/reply.html\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-url\"\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记当前文章的发布日期\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003etime\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"dt-published\"\u003c/span\u003e \u003cspan\u003edatetime\u003c/span\u003e=\u003cspan\u003e\"2018-06-30T17:15:00-0700\"\u003c/span\u003e\u0026gt;July 30, 2018\u0026lt;/\u003cspan\u003etime\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ediv\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\n\n\u003cp\u003e\n具体如何标记,要看你博客中的 HTML 标记是如何排布的,在标记时注意层级关系就好。测试阶段可以多利用 \u003ca href=\"https://microformats.org/wiki/parsers\"\u003eMicroformats Parsers\u003c/a\u003e 解析你的文章,检查解析出来的内容是否符合需要。\n\u003c/p\u003e\n\n\u003cp\u003e\n都设置好之后就可以向集成了 Webmention 的网站发送通知了,你可以:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e找到引用文章的 Webmention 入口,填写你的文章 URL 并提交\u003c/li\u003e\n\u003cli\u003e自己构建 POST 请求,或用第三方服务,如 \u003ca href=\"https://telegraph.p3k.io/\"\u003eTelegraph\u003c/a\u003e 手动发送\u003c/li\u003e\n\u003cli\u003e考虑集成 \u003ca href=\"https://webmention.app/\"\u003ewebmention.app\u003c/a\u003e 等实现自动发送\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n一般发送之后都会有响应,如果你的 Webmention 没有展示出来,可以基于返回信息进行问题排查。\n\u003c/p\u003e\n\n\n\n\n\u003ch2\u003e一些问题\u003c/h2\u003e\n\n\n\u003ch3\u003e常见问题\u003c/h3\u003e\n\u003cp\u003e\n大部分疑惑 \u003ca href=\"https://indieweb.org/Webmention-faq\"\u003eWebmention-faq | IndieWeb\u003c/a\u003e 中都有解答。\n\u003c/p\u003e\n\n\u003cp\u003e\n分享一些比较常见的问题:\n\u003c/p\u003e\n\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Do_webmentions_work_only_when_both_sites_use_webmentions?\"\u003eDo webmentions work only when both sites use webmentions?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#How_do_you_know_if_a_website_uses_webmentions?\"\u003eHow do you know if a website uses webmentions?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Which_links_should_webmentions_be_sent_to\"\u003eWhich links should webmentions be sent to\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Should_webmentions_be_sent_for_removals\"\u003eShould webmentions be sent for removals\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003e关于 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-in-reply-to%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20reply%20to%20(i.e.%20doesn%E2%80%99t%20make%20sense%20without%20context%2C%20could%20show%20up%20in%20comment%20thread)%2C%20optionally%20an%20embedded%20h-cite%20(reply-context)%20(example)\"\u003eu-in-reply-to\u003c/a\u003e 的使用\u003c/h3\u003e\n\u003cp\u003e\n\u003ccode\u003eu-in-reply-to\u003c/code\u003e 用于标记 h-entry 中要回复的链接,应该结合 \u003ccode\u003ee-content\u003c/code\u003e 标记回应的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果只是引用了一些链接,并没有对于这些链接的回应,不需要用 \u003ccode\u003eu-in-reply-to\u003c/code\u003e 标记,直接发送 Webmention 就好了。\n\u003c/p\u003e\n\n\n\n\u003ch3\u003e关于 \u003ca href=\"https://microformats.org/wiki/h-entry\"\u003eh-entry\u003c/a\u003e 的使用\u003c/h3\u003e\n\u003cp\u003e\n尽管可以设置多个 h-entry,但我觉得一篇文章一个 h-entry 就够了。\n\u003c/p\u003e\n\n\u003cp\u003e\n原因是 h-entry 往往需要指定文章标题、作者、发布和更新时间、内容等,这和一篇文章的内容是刚好对应上的。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果标记多个 h-entry,比较难保证每个 h-entry 都有这些信息,尽管 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=the%20%22datetime%22%20property.-,what%20is%20the%20bare%20minimum%20list%20of%20required%20properties%20on%20an,a%20nested%20h-card%20with%20author%20details%20like%20name%2C%20photo%2C%20url.,-Examples%20in%20the\"\u003eh-entry 不要求包含任一属性\u003c/a\u003e。\n\u003c/p\u003e\n\n\u003cp\u003e\n我的建议是:\n\u003c/p\u003e\n\n\u003cul\u003e\u003cli\u003eh-entry 设置在包含文章内容、作者信息、发布日期等的父元素上\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\ne-content 设置在包含整篇文章内容的元素上\n\u003c/p\u003e\n\n\u003cp\u003e\n好处是,只要在文章中的链接都能被发现,不需要额外再标记什么。缺点是,e-content 标记的内容可能太多,导致实际回复的部分被淹没其中。\n\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003ewebmention.io 的 target 需要完全匹配\u003c/h3\u003e\n\u003cp\u003e\n见 \u003ca href=\"https://github.com/aaronpk/webmention.io/issues/229#issuecomment-3602563563\"\u003eWhen URL has hash,webmention.io'a API not reponse data #229\u003c/a\u003e。\n\u003c/p\u003e\n\n\u003cp\u003e\n有的 webmention 的发送时的 URL 是 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,通过 webmention.io 的 \u003ca href=\"https://github.com/aaronpk/webmention.io?tab=readme-ov-file#api\"\u003eAPI\u003c/a\u003e,target 参数设置为 \u003ccode\u003ehttps://domain/page.html\u003c/code\u003e 是无法获取到数据的,需要将 target 设置为 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,完全匹配才行,因为目前存储的就是完整的 URL。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果 target 是 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,注意需要将 \u003ccode\u003e#\u003c/code\u003e \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent\"\u003e转义\u003c/a\u003e 成 \u003ccode\u003e%23\u003c/code\u003e 。\n\u003c/p\u003e\n\u003cp\u003e\n我目前的处理方法是用 \u003ca href=\"https://github.com/aaronpk/webmention.io?tab=readme-ov-file#find-all-links-to-your-domain\"\u003e基于域名获取所有数据的 API\u003c/a\u003e 先获取所有的数据,然后基于页面的 URL 进行过滤。\n\u003c/p\u003e\n\n\n\n\u003ch3\u003e发送了 webmention 但是没有显示出来\u003c/h3\u003e\n\u003cp\u003e\n一种可能是,webmention 要求源页面中包含目标页面的链接,而有的源页面是由 JS 动态渲染的,不是静态的,导致 webmention 无法从源页面找到目标页面的链接,而认为源页面没有发送 webmention。\n\u003c/p\u003e\n\n\u003cp\u003e\n排查的方法是,在浏览器中查看网络请求,找到源页面返回的内容,搜索一下内容中是否包含目标页面的链接。\n\u003c/p\u003e\n\n\u003cp\u003e\n也可能是网站显示的问题,可以尝试联系作者。\n\u003c/p\u003e\n\n\n\n\n\u003ch2\u003e写在最后\u003c/h2\u003e\n\u003cp\u003e\n以为接入挺简单的,但实际做还是折腾了两天,果真是「纸上得来终觉浅,绝知此事要躬行」呀。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你链接了我的文章,欢迎你向我发送 Webmention,这样就建立了文章之间的链接。一方面我可以看看别人引用时的评论;另一方面,其他读者也可以通过 Webmention 知道你的文章。\n\u003c/p\u003e\n\n\u003cp\u003e\n我认为这是一件共赢的事,你引用了我的链接,帮我推广了给更多人;而你向引用的文章发送 Webmention,也能帮忙推广你的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n何乐而不为?\n\u003c/p\u003e\n\n\n\n\u003ch2\u003e其他参考文章\u003c/h2\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://jason-memo.dev/posts/webmention/\"\u003e透過 webmention 來搜集 blog 的社群迴響\u003c/a\u003e by Jason Chen\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://blog.xiang578.com/note/641ea60f-a31e-4979-9327-c50509c146e3.html\"\u003eWebmention 实现参考\u003c/a\u003e by Runye\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.owenyoung.com/en/blog/indieweb/\"\u003eNow, I'm in IndieWeb?\u003c/a\u003e by Owen Young\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://blog.cytrogen.icu/posts/1de\"\u003e在 Hexo 项目中添加 Webmention\u003c/a\u003e by Cytrogen\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.geedea.pro/article/webmention/\"\u003eWebmention 简明指南\u003c/a\u003e by Eltrac\u003c/li\u003e\n\u003c/ul\u003e",
+ "text": "给博客添加 Webmention\n目录\n\n什么是 Webmention\n为什么接入 Webmention\n如何接入 Webmention\n一些问题\n写在最后\n其他参考文章\n\n???? The Great Escape Of Our Time - 椅子乐团 The Chairs\n\n\n什么是 Webmention\n\n\nWebmention 是一种通知,表明一个 URL 链接到另一个 URL。\n\n\n\n例如,Alice 在她的博客上写了一篇有趣的帖子。随后 Bob 在自己的网站上写了一篇回复她的帖子,并链接回 Alice 的原始帖子。\nBob 的发布软件向 Alice 发送一个 Webmention,通知她的文章被回复了,\nAlice 的软件可以将该回复显示为原始帖子上的评论。\n\n\n\nSource\n\n\n\n\nWebmention 和评论差不多,只是它的门槛相对高一点,需要你写一篇文章,并链接到你想评论的文章。\n(或者在社交媒体如 BlueSky、Mastodon 上发一个帖子,引用文章的链接)\n\n\n\n如果对方支持了 Webmention,你发送 Webmention 通知后,对方就会将你的内容显示出来。\n\n\nWebmention 的大致流程\n\n图1 Webmention 的大致流程,参考 https://www.w3.org/TR/webmention/#protocol-summary\n\n\n为什么接入 Webmention\n\n\n实现跨站点的对话。当你链接到某个网站时,你可以发送一个 Webmention 来通知它。如果该网站支持 Webmention,那么该网站可能会将你的帖子显示为评论、赞或其他回应,就这样,你就实现了从一个站点到另一个站点的对话!\n\n\n\nSource\n\n\n\n\n我觉得 Webmention 和集成在博客中的评论系统是类似的。\n\n\n\n如果你要回应一篇文章,通过 Webmention,你需要写一篇文章链接到这篇文章,并发送一个 Webmention 通知。通过如 Bridgy 之类的服务,也可以收集社交网络上(Blusky、Mastodon 等)关于文章的回应,例如点赞、转发等。\n\n\n\n但我觉得并没有比集成于博客的评论系统更方便。\n\n\n\n从数据层面看,除非自己买服务器搭建 Webmention,否则用第三方提供的服务,数据依然不在自己的手上。\n\n\n\n所以我为什么要接入 Webmention?\n\n\n\n最开始是在 我想让自己说话不那么“端着” | Owen Young 中了解到 Webmention,当时觉得有些麻烦。\n\n\n\n最近网上冲浪的时候,看到不少博客都有集成 Webmention,然后了解了一下 webmention.io 的使用,看起来不麻烦,就想着集成看看。\n\n\n\n非要找个理由的话,就是折腾一下,好玩吧。\n\n\n\n\n如何接入 Webmention\n\n如果自己搭建的话,可以参照 Webmention 规范 实现;或者找现成的工具,你可以在 Webmention | IndieWeb 找到很多工具和服务。\n\n\n\n我目前实现很简单,接收依赖 webmention.io 提供的服务,需要自己编写一点 脚本 调用 API;发送通过手动触发;麻烦一些的地方是给博客添加 microformats 。\n\n\n\n作为接收方\n\n接收我使用 webmention.io 提供的服务,按照 How to Set Up Your Website for IndieLogin.com 的说明进行设置。\n\n\n\n我用 GitHub 进行验证,需要在 GitHub Profile 中包含我的网站,同时在网站添加一个链接。\n\n\n\n\n\n图2 我的 GitHub Profile 页面,我把网站的地址添加到了 Profile 中\n\u003chead\u003e\n \u003c!-- 省略其他内容 --\u003e\n \u003clink href=\"https://github.com/spike-leung\" rel=\"me\"\u003e\n \u003c!-- 省略其他内容 --\u003e\n\u003c/head\u003e\n\n\n\n\n这样就能通过 webmention.io 的验证了。\n\n\n\n接下来按照 webmention.io 提供的 API 获取 Webmentions 的数量和内容,需要在页面上添加 HTML 元素,写 一些 JS 代码 调用 API 渲染数据(也可以用 webmention.js),再写点 CSS 优化一下样式。\n\n\n\n如果你打算渲染 Webmentions 返回的 HTML,需要注意 Cross-site scripting (XSS) 攻击。\n\n\n防止 XSS 攻击\n防止 XSS 攻击,Trusted Types API 看起来不错,可惜浏览器支持度不够。\n\n\n\n防御 XSS 主要从两方面入手:\n\n净化 (sanitize) 用户输入的内容。可以使用 DOMPurify 处理。\n使用 Content Security Policy (CSP) 限制执行。Netlify 有插件支持,倒是方便了许多。要注意的是,当开启了 CSP,一些行内的脚本,如写在元素上的 onclick、 onchange 等会被阻止执行,需要将他们挪动到 JS 文件里。\n\n也可以期待一下 Element: setHTML() method 被广泛支持,它提供了一种 XSS 安全的方法用于插入 HTML 内容到页面中。\n\n\n搭建好之后,可以用 Webmention Rocks! 提供的服务进行测试。\n\n\n\n至于查看 Webmentions 也有几种方法:\n\n到对应的页面下看\n订阅 webmention.io 提供的 Mentions Feed\n使用 webmention.io 提供的 Web Hook 通知自己\n到 webmention.io 的 Dashbaord 查看\n作为发送方\n\n作为发送方,你只需要在你的文章中包含对方的链接,就可以向对方发送 Webmention 了。\n\n\n\n但是如果你想让你发送的内容更丰富一些,就需要通过 microformats 标记网站信息,如用户名、头像、内容、你要提及的链接等,从而让 Webmention 解析展示。\n\n\n\n按理说只要包含了对方链接,对方就能收到 Webmention。\n\n\n\n但我发送后却收到了「The Microformats at the source URL do not contain a link to the target URL.」的错误提示。\n\n\n\n可能是因为我使用 microformats 标记了内容,此时需要确保 microformats 解析后的内容中,包含对方的 URL。\n\n\n最主要的标记是 h-card 和 h-entry,h-card 标记用户信息;\nh-entry 标记内容信息,标记的部分会作为 Webmention 的内容呈现。\n\n\n\n关于 h-card 和 h-entry 的作用,推荐看 Sending your First Webmention from Scratch,文章循序渐进地引导你添加相应的标记,并且有对应的示例,同时文章本身也可以用来测试 Webmention 的发送。\n\n\n\nmicroformats 这些标记,可以和 HTML 做类比,它也是有层级关系的,最终会解析成一个 JSON 的树形结构。在你测试的时候,可以从 Microformats Parsers 找一个 parser 检查你的文章解析出来的内容。\n\n\n\n关于 h-entry\n\n\n\nwhat is the bare minimum list of required properties on an h-entry 中回答道,没有任何 h-entry 的属性是强制要求的。\n\n\n\n但推荐至少包含:\n\ne-content 标记文章内容,被标记的内容会作为 Webmention 的内容被发送\np-name 标记文章标题\np-author 标记作者信息,一般会和 h-card 结合使用\n\n一些我建议加上的:\n\nu-in-reply-to 标记你回应的链接。此外 u-like-of、u-report-of 等可以用于标记不同的引用目的\ndt-published 标记文章的发布日期\ndt-updated 标记文章的更新日期\n\n关于 h-card\n\n\n\nh-card 是用来标记用户信息的,介绍一些我觉得比较有用的:\n\np-name 标记个人或组织的全称\nu-email 标记邮箱,一般标记在 mailto 链接上\nu-logo 标记你的 logo,一般标记在 \u003cimg\u003e 标签上\nu-photo 标记你的头像,一般标记在 \u003cimg\u003e 标签上\nu-url 标记你的主页,一般标记在一个链接上\np-note 标记额外信息,有人会用来写自我介绍\n\n除了这些,还有标记地址、性别、国籍、出生日期、工作等,感兴趣可以自行探索。\n\n\n\nh-card 可以结合 h-entry 的 p-author 用于标记文章的作者信息,在这种场景下,h-entry 需要是 h-card 的父元素。\n\n\n\n综上,一个相对完整的 microformats 标记是这样的:\n\n\n\n\u003c!doctype html\u003e\n\u003cmeta charset=\"utf-8\"\u003e\n\u003ctitle\u003eHello World\u003c/title\u003e\n\u003cbody\u003e\n \u003cdiv class=\"h-entry\"\u003e \u003c!-- 注意 h-entry 是其他属性的父元素,包含了 h-card --\u003e\n \u003cdiv class=\"p-author h-card\"\u003e \u003c!-- 使用 h-card 结合 p-author 标记作者信息 --\u003e\n \u003cimg src=\"https://aaronpk.com/images/aaronpk.jpg\" class=\"u-photo\" width=\"40\"\u003e\n \u003ca href=\"https://aaronpk.com/\" class=\"u-url p-name\"\u003eAaron Parecki\u003c/a\u003e\n \u003c/div\u003e\n \u003c!-- 标记引用的链接,表示回复 --\u003e\n \u003cp\u003ein reply to: \u003ca class=\"u-in-reply-to\" href=\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003e@aaronpk\u003c/a\u003e\u003c/p\u003e\n \u003c!-- 标记回复的内容 --\u003e\n \u003cp class=\"e-content\"\u003eTrying out this guide to sending webmentions\u003c/p\u003e\n \u003cp\u003e\n \u003c!-- 标记当前文章的 URL --\u003e\n \u003ca href=\"https://aaronpk.com/reply.html\" class=\"u-url\"\u003e\n \u003c!-- 标记当前文章的发布日期 --\u003e\n \u003ctime class=\"dt-published\" datetime=\"2018-06-30T17:15:00-0700\"\u003eJuly 30, 2018\u003c/time\u003e\n \u003c/a\u003e\n \u003c/p\u003e\n \u003c/div\u003e\n\u003c/body\u003e\n\n\n\n\n具体如何标记,要看你博客中的 HTML 标记是如何排布的,在标记时注意层级关系就好。测试阶段可以多利用 Microformats Parsers 解析你的文章,检查解析出来的内容是否符合需要。\n\n\n\n都设置好之后就可以向集成了 Webmention 的网站发送通知了,你可以:\n\n找到引用文章的 Webmention 入口,填写你的文章 URL 并提交\n自己构建 POST 请求,或用第三方服务,如 Telegraph 手动发送\n考虑集成 webmention.app 等实现自动发送\n\n一般发送之后都会有响应,如果你的 Webmention 没有展示出来,可以基于返回信息进行问题排查。\n\n\n\n\n\n一些问题\n\n\n常见问题\n\n大部分疑惑 Webmention-faq | IndieWeb 中都有解答。\n\n\n\n分享一些比较常见的问题:\n\n\nDo webmentions work only when both sites use webmentions?\nHow do you know if a website uses webmentions?\nWhich links should webmentions be sent to\nShould webmentions be sent for removals\n关于 u-in-reply-to 的使用\n\nu-in-reply-to 用于标记 h-entry 中要回复的链接,应该结合 e-content 标记回应的内容。\n\n\n\n如果只是引用了一些链接,并没有对于这些链接的回应,不需要用 u-in-reply-to 标记,直接发送 Webmention 就好了。\n\n\n\n\n关于 h-entry 的使用\n\n尽管可以设置多个 h-entry,但我觉得一篇文章一个 h-entry 就够了。\n\n\n\n原因是 h-entry 往往需要指定文章标题、作者、发布和更新时间、内容等,这和一篇文章的内容是刚好对应上的。\n\n\n\n如果标记多个 h-entry,比较难保证每个 h-entry 都有这些信息,尽管 h-entry 不要求包含任一属性。\n\n\n\n我的建议是:\n\n\nh-entry 设置在包含文章内容、作者信息、发布日期等的父元素上\n\ne-content 设置在包含整篇文章内容的元素上\n\n\n\n好处是,只要在文章中的链接都能被发现,不需要额外再标记什么。缺点是,e-content 标记的内容可能太多,导致实际回复的部分被淹没其中。\n\nwebmention.io 的 target 需要完全匹配\n\n见 When URL has hash,webmention.io'a API not reponse data #229。\n\n\n\n有的 webmention 的发送时的 URL 是 https://domain/page.html#abc ,通过 webmention.io 的 API,target 参数设置为 https://domain/page.html 是无法获取到数据的,需要将 target 设置为 https://domain/page.html#abc ,完全匹配才行,因为目前存储的就是完整的 URL。\n\n\n\n如果 target 是 https://domain/page.html#abc ,注意需要将 # 转义 成 %23 。\n\n\n我目前的处理方法是用 基于域名获取所有数据的 API 先获取所有的数据,然后基于页面的 URL 进行过滤。\n\n\n\n\n发送了 webmention 但是没有显示出来\n\n一种可能是,webmention 要求源页面中包含目标页面的链接,而有的源页面是由 JS 动态渲染的,不是静态的,导致 webmention 无法从源页面找到目标页面的链接,而认为源页面没有发送 webmention。\n\n\n\n排查的方法是,在浏览器中查看网络请求,找到源页面返回的内容,搜索一下内容中是否包含目标页面的链接。\n\n\n\n也可能是网站显示的问题,可以尝试联系作者。\n\n\n\n\n\n写在最后\n\n以为接入挺简单的,但实际做还是折腾了两天,果真是「纸上得来终觉浅,绝知此事要躬行」呀。\n\n\n\n如果你链接了我的文章,欢迎你向我发送 Webmention,这样就建立了文章之间的链接。一方面我可以看看别人引用时的评论;另一方面,其他读者也可以通过 Webmention 知道你的文章。\n\n\n\n我认为这是一件共赢的事,你引用了我的链接,帮我推广了给更多人;而你向引用的文章发送 Webmention,也能帮忙推广你的内容。\n\n\n\n何乐而不为?\n\n\n\n\n其他参考文章\n透過 webmention 來搜集 blog 的社群迴響 by Jason Chen\nWebmention 实现参考 by Runye\nNow, I'm in IndieWeb? by Owen Young\n在 Hexo 项目中添加 Webmention by Cytrogen\nWebmention 简明指南 by Eltrac"
+ },
+ "published": "2025-09-25T21:24:00",
+ "received": "2026-03-10T17:08:32Z",
+ "source": "https://taxodium.ink/add-webmention-to-blog.html",
+ "type": "mention-of",
+ "url": "https://taxodium.ink/add-webmention-to-blog.html"
+ },
+ {
+ "author": {
"name": "伏枥",
"photo": "https://avatars.webmention.io/c7.io/3b024daedc46bd2daab952cc2c59cc2fd62b234725ef25e1edd9a6cfe1106bda.jpg",
"type": "card",
@@ -370,37 +531,6 @@
},
{
"author": {
- "name": "花島Saki",
- "photo": "https://avatars.webmention.io/files.mstdn.party/f114ba351fb35db23831a3d172a154cc85b008d835c950009a711c648d3e5679.jpg",
- "type": "card",
- "url": "https://mstdn.party/@hanajima_saki"
- },
- "content": null,
- "published": null,
- "received": "2026-03-10T16:59:10Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B3bjSNrhW69SacjQdk",
- "type": "like-of",
- "url": "https://akk.eltr.ac/notice/B47Na8WhcQVAf7k6bI#favorited-by-B3bjSNrhW69SacjQdk"
- },
- {
- "author": {
- "name": "Spike Leung",
- "photo": "https://avatars.webmention.io/taxodium.ink/2b954e9d7ff8da1cb55e49fc098ea06f464c9ffd1872e1f92cc2ac1bb10ad7c4.png",
- "type": "card",
- "url": "https://taxodium.ink"
- },
- "content": {
- "html": "\u003ch1 class=\"p-name\"\u003e给博客添加 Webmention\u003c/h1\u003e\n\u003ch2\u003e目录\u003c/h2\u003e\n\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D459C268-A454-4D43-9E49-97D0A90C2F67\"\u003e什么是 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#E55EE851-CF6C-4FC6-A4F8-94FD38BFA17F\"\u003e为什么接入 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D55D3AFA-42A0-4D14-A52F-FB34162E31DD\"\u003e如何接入 Webmention\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#D2EB3BEC-396F-43D6-BA15-A89E38A671F8\"\u003e一些问题\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#967313DB-C374-4182-8F81-AE96666BF2CD\"\u003e写在最后\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://taxodium.ink/add-webmention-to-blog.html#806C5BB0-D8CB-4AD8-BC52-2866C9072B41\"\u003e其他参考文章\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\n???? The Great Escape Of Our Time - 椅子乐团 The Chairs\n\u003c/p\u003e\n\n\u003ch2\u003e什么是 Webmention\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\nWebmention 是一种通知,表明一个 URL 链接到另一个 URL。\n\u003c/p\u003e\n\n\u003cp\u003e\n例如,Alice 在她的博客上写了一篇有趣的帖子。随后 Bob 在自己的网站上写了一篇回复她的帖子,并链接回 Alice 的原始帖子。\nBob 的发布软件向 Alice 发送一个 Webmention,通知她的文章被回复了,\nAlice 的软件可以将该回复显示为原始帖子上的评论。\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://www.w3.org/TR/webmention/#introduction-p-1:~:text=A%20Webmention%20is,the%20original%20post.\"\u003eSource\u003c/a\u003e\n\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003cp\u003e\nWebmention 和评论差不多,只是它的门槛相对高一点,需要你写一篇文章,并链接到你想评论的文章。\n(或者在社交媒体如 BlueSky、Mastodon 上发一个帖子,引用文章的链接)\n\u003c/p\u003e\n\n\u003cp\u003e\n如果对方支持了 Webmention,你发送 Webmention 通知后,对方就会将你的内容显示出来。\n\u003c/p\u003e\n\nWebmention 的大致流程\u003ca href=\"https://taxodium.ink/images/add-webmention-to-blog/mermaid.png\"\u003e\u003cimg src=\"https://taxodium.ink/images/add-webmention-to-blog/mermaid.png\" alt=\"mermaid.png\" /\u003e\u003c/a\u003e\n\n\u003cspan\u003e图1 \u003c/span\u003eWebmention 的大致流程,参考 \u003ca href=\"https://www.w3.org/TR/webmention/#protocol-summary\"\u003ehttps://www.w3.org/TR/webmention/#protocol-summary\u003c/a\u003e\n\n\n\u003ch2\u003e为什么接入 Webmention\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\n\u003cb\u003e实现跨站点的对话。\u003c/b\u003e当你链接到某个网站时,你可以发送一个 Webmention 来通知它。如果该网站支持 Webmention,那么该网站可能会将你的帖子显示为评论、赞或其他回应,就这样,你就实现了从一个站点到另一个站点的对话!\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://indieweb.org/Webmention#:~:text=Enables%20cross-site%20conversations.%20When%20you%20link%20to%20a%20website%2C%20you%20can%20send%20it%20a%20Webmention%20to%20notify%20it.%20If%20it%20supports%20Webmentions%2C%20then%20that%20website%20may%20display%20your%20post%20as%20a%20comment%2C%20like%2C%20or%20other%20response%2C%20and%20presto%2C%20you%E2%80%99re%20having%20a%20conversation%20from%20one%20site%20to%20another!\"\u003eSource\u003c/a\u003e\n\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003cp\u003e\n我觉得 Webmention 和集成在博客中的评论系统是类似的。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你要回应一篇文章,通过 Webmention,你需要写一篇文章链接到这篇文章,并发送一个 Webmention 通知。通过如 \u003ca href=\"https://brid.gy/\"\u003eBridgy\u003c/a\u003e 之类的服务,也可以收集社交网络上(Blusky、Mastodon 等)关于文章的回应,例如点赞、转发等。\n\u003c/p\u003e\n\n\u003cp\u003e\n但我觉得并没有比集成于博客的评论系统更方便。\n\u003c/p\u003e\n\n\u003cp\u003e\n从数据层面看,除非自己买服务器搭建 Webmention,否则用第三方提供的服务,数据依然不在自己的手上。\n\u003c/p\u003e\n\n\u003cp\u003e\n所以我为什么要接入 Webmention?\n\u003c/p\u003e\n\n\u003cp\u003e\n最开始是在 \u003ca href=\"https://www.owenyoung.com/blog/de-roboticization/#2-xie-bo-ke%20:~:text=%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E6%B2%A1%E6%9C%89%E8%AF%84%E8%AE%BA%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%AF%84%E8%AE%BA%E5%8A%9F%E8%83%BD%E4%BC%9A%E5%85%B6%E5%AE%9E%E4%BC%9A%E8%AE%A9%E6%88%91%E5%BC%95%E5%85%A5%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%9A%84%E5%8C%85%E8%A2%B1%E6%84%9F%E3%80%82%E6%88%91%E8%A7%89%E5%BE%97%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E7%9A%84%E5%A5%BD%E5%8A%9E%E6%B3%95%E6%98%AF%E5%BC%95%E5%85%A5webmention%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E4%BA%BA%E6%83%B3%E8%A6%81%E5%9B%9E%E5%BA%94%EF%BC%8C%E5%BE%97%E6%8F%90%E4%BA%A4%E8%87%AA%E5%B7%B1%E7%9A%84%E5%9B%9E%E5%BA%94%E7%BD%91%E5%9D%80%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E8%AF%84%E8%AE%BA%E6%A1%86%E9%87%8C%E7%95%99%E4%B8%8B%E4%B8%89%E8%A8%80%E4%B8%A4%E8%AF%AD%E3%80%82%E8%BF%99%E6%8F%90%E9%AB%98%E4%BA%86%E8%AF%84%E8%AE%BA%E7%9A%84%E6%88%90%E6%9C%AC%EF%BC%8C%E9%BC%93%E5%8A%B1%E6%83%B3%E8%A6%81%E7%95%99%E8%A8%80%E7%9A%84%E4%BA%BA%E6%8B%A5%E6%9C%89%E8%87%AA%E5%B7%B1%E7%9A%84%E5%8D%9A%E5%AE%A2%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%86%99%E4%B8%80%E4%BA%9B%E7%BB%8F%E8%BF%87%E6%80%9D%E8%80%83%E7%9A%84%E8%AF%9D%E8%AF%AD%E3%80%82%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2%E5%B7%B2%E7%BB%8F%E6%94%AF%E6%8C%81%E4%BA%86%20Webmention%EF%BC%8C%E6%88%91%E5%9C%A8Now%2C%20I%E2%80%99m%20in%20IndieWeb%3F%E9%87%8C%E6%9C%89%E8%AE%B0%E5%BD%95%E6%88%91%E7%9A%84%E5%AE%9E%E7%8E%B0%E3%80%82\"\u003e我想让自己说话不那么“端着” | Owen Young\u003c/a\u003e 中了解到 Webmention,当时觉得有些麻烦。\n\u003c/p\u003e\n\n\u003cp\u003e\n最近网上冲浪的时候,看到不少博客都有集成 Webmention,然后了解了一下 \u003ca href=\"https://webmention.io/\"\u003ewebmention.io\u003c/a\u003e 的使用,看起来不麻烦,就想着集成看看。\n\u003c/p\u003e\n\n\u003cp\u003e\n非要找个理由的话,就是折腾一下,好玩吧。\n\u003c/p\u003e\n\n\n\n\u003ch2\u003e如何接入 Webmention\u003c/h2\u003e\n\u003cp\u003e\n如果自己搭建的话,可以参照 \u003ca href=\"https://www.w3.org/TR/webmention\"\u003eWebmention 规范\u003c/a\u003e 实现;或者找现成的工具,你可以在 \u003ca href=\"https://indieweb.org/Webmention\"\u003eWebmention | IndieWeb\u003c/a\u003e 找到很多工具和服务。\n\u003c/p\u003e\n\n\u003cp\u003e\n我目前实现很简单,接收依赖 webmention.io 提供的服务,需要自己编写一点 \u003ca href=\"https://taxodium.ink/js/webmention.js\"\u003e脚本\u003c/a\u003e 调用 API;发送通过手动触发;麻烦一些的地方是给博客添加 \u003ca href=\"https://microformats.org/wiki/Main_Page\"\u003emicroformats\u003c/a\u003e 。\n\u003c/p\u003e\n\n\n\u003ch3\u003e作为接收方\u003c/h3\u003e\n\u003cp\u003e\n接收我使用 webmention.io 提供的服务,按照 \u003ca href=\"https://indielogin.com/setup\"\u003eHow to Set Up Your Website for IndieLogin.com\u003c/a\u003e 的说明进行设置。\n\u003c/p\u003e\n\n\u003cp\u003e\n我用 GitHub 进行验证,需要在 GitHub Profile 中包含我的网站,同时在网站添加一个链接。\n\u003c/p\u003e\n\n\n\u003ca href=\"https://taxodium.ink/images/add-webmention-to-blog/github-profile.png\"\u003e\u003cimg src=\"https://taxodium.ink/images/add-webmention-to-blog/github-profile.png\" alt=\"github-profile.png\" /\u003e\u003c/a\u003e\n\n\u003cspan\u003e图2 \u003c/span\u003e我的 GitHub Profile 页面,我把网站的地址添加到了 Profile 中\n\u003cpre\u003e\u003ccode\u003e\u0026lt;\u003cspan\u003ehead\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e省略其他内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003elink\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://github.com/spike-leung\"\u003c/span\u003e \u003cspan\u003erel\u003c/span\u003e=\u003cspan\u003e\"me\"\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e省略其他内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n\u0026lt;/\u003cspan\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\n\n\u003cp\u003e\n这样就能通过 webmention.io 的验证了。\n\u003c/p\u003e\n\n\u003cp\u003e\n接下来按照 webmention.io 提供的 API 获取 Webmentions 的数量和内容,需要在页面上添加 HTML 元素,写 \u003ca href=\"https://taxodium.ink/js/webmention.js\"\u003e一些 JS 代码\u003c/a\u003e 调用 API 渲染数据(也可以用 \u003ca href=\"https://github.com/PlaidWeb/webmention.js\"\u003ewebmention.js\u003c/a\u003e),再写点 CSS 优化一下样式。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你打算渲染 Webmentions 返回的 HTML,需要注意 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS\"\u003eCross-site scripting (XSS)\u003c/a\u003e 攻击。\n\u003c/p\u003e\n\n防止 XSS 攻击\u003cp\u003e\n防止 XSS 攻击,\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types\"\u003eTrusted Types API\u003c/a\u003e 看起来不错,可惜浏览器支持度不够。\n\u003c/p\u003e\n\n\u003cp\u003e\n防御 XSS 主要从两方面入手:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e净化 (sanitize) 用户输入的内容。可以使用 \u003ca href=\"https://github.com/cure53/DOMPurify\"\u003eDOMPurify\u003c/a\u003e 处理。\u003c/li\u003e\n\u003cli\u003e使用 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP\"\u003eContent Security Policy (CSP)\u003c/a\u003e 限制执行。\u003ca href=\"https://www.netlify.com/blog/general-availability-content-security-policy-csp-nonce-integration/\"\u003eNetlify 有插件支持\u003c/a\u003e,倒是方便了许多。要注意的是,当开启了 CSP,一些行内的脚本,如写在元素上的 onclick、 onchange 等会被阻止执行,需要将他们挪动到 JS 文件里。\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n也可以期待一下 \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Element/setHTML\"\u003eElement: setHTML() method\u003c/a\u003e 被广泛支持,它提供了一种 XSS 安全的方法用于插入 HTML 内容到页面中。\n\u003c/p\u003e\n\u003cp\u003e\n搭建好之后,可以用 \u003ca href=\"https://webmention.rocks/#:~:text=Testing%20your%20Receiver\"\u003eWebmention Rocks!\u003c/a\u003e 提供的服务进行测试。\n\u003c/p\u003e\n\n\u003cp\u003e\n至于查看 Webmentions 也有几种方法:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e到对应的页面下看\u003c/li\u003e\n\u003cli\u003e订阅 webmention.io 提供的 \u003ca href=\"https://webmention.io/settings\"\u003eMentions Feed\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e使用 webmention.io 提供的 \u003ca href=\"https://webmention.io/settings/webhooks\"\u003eWeb Hook\u003c/a\u003e 通知自己\u003c/li\u003e\n\u003cli\u003e到 webmention.io 的 \u003ca href=\"https://webmention.io/dashboard\"\u003eDashbaord\u003c/a\u003e 查看\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003e作为发送方\u003c/h3\u003e\n\u003cp\u003e\n作为发送方,你只需要在你的文章中包含对方的链接,就可以向对方发送 Webmention 了。\n\u003c/p\u003e\n\n\u003cp\u003e\n但是如果你想让你发送的内容更丰富一些,就需要通过 \u003ca href=\"https://microformats.org/wiki/Main_Page\"\u003emicroformats\u003c/a\u003e 标记网站信息,如用户名、头像、内容、你要提及的链接等,从而让 Webmention 解析展示。\n\u003c/p\u003e\n\n\u003cp\u003e\n按理说只要包含了对方链接,对方就能收到 Webmention。\n\u003c/p\u003e\n\n\u003cp\u003e\n但我发送后却收到了「The Microformats at the source URL do not contain a link to the target URL.」的错误提示。\n\u003c/p\u003e\n\n\u003cp\u003e\n可能是因为我使用 microformats 标记了内容,此时需要确保 microformats 解析后的内容中,包含对方的 URL。\n\u003c/p\u003e\n\u003cp\u003e\n最主要的标记是 \u003ca href=\"https://microformats.org/wiki/h-card\"\u003eh-card\u003c/a\u003e 和 \u003ca href=\"https://microformats.org/wiki/h-entry\"\u003eh-entry\u003c/a\u003e,h-card 标记\u003cem\u003e用户\u003c/em\u003e信息;\nh-entry 标记\u003cem\u003e内容\u003c/em\u003e信息,标记的部分会作为 Webmention 的内容呈现。\n\u003c/p\u003e\n\n\u003cp\u003e\n关于 h-card 和 h-entry 的作用,推荐看 \u003ca href=\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003eSending your First Webmention from Scratch\u003c/a\u003e,文章循序渐进地引导你添加相应的标记,并且有对应的示例,同时文章本身也可以用来测试 Webmention 的发送。\n\u003c/p\u003e\n\n\u003cp\u003e\nmicroformats 这些标记,可以和 HTML 做类比,它也是有层级关系的,最终会解析成一个 JSON 的树形结构。在你测试的时候,可以从 \u003ca href=\"https://microformats.org/wiki/parsers\"\u003eMicroformats Parsers\u003c/a\u003e 找一个 parser 检查你的文章解析出来的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003cb\u003e关于 h-entry\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=the%20%22datetime%22%20property.-,what%20is%20the%20bare%20minimum%20list%20of%20required%20properties%20on%20an,a%20nested%20h-card%20with%20author%20details%20like%20name%2C%20photo%2C%20url.,-Examples%20in%20the\"\u003ewhat is the bare minimum list of required properties on an h-entry\u003c/a\u003e 中回答道,没有任何 h-entry 的属性是强制要求的。\n\u003c/p\u003e\n\n\u003cp\u003e\n但推荐至少包含:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=e-content%20-%20full%20content%20of%20the%20entry\"\u003ee-content\u003c/a\u003e 标记文章内容,被标记的内容会作为 Webmention 的内容被发送\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=p-name%20-%20entry%20name/title\"\u003ep-name\u003c/a\u003e 标记文章标题\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=p-author%20-%20who%20wrote%20the%20entry%2C%20optionally%20embedded%20h-card(s)\"\u003ep-author\u003c/a\u003e 标记作者信息,一般会和 h-card 结合使用\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n一些我建议加上的:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-in-reply-to%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20reply%20to%20(i.e.%20doesn%E2%80%99t%20make%20sense%20without%20context%2C%20could%20show%20up%20in%20comment%20thread)%2C%20optionally%20an%20embedded%20h-cite%20(reply-context)%20(example)\"\u003eu-in-reply-to\u003c/a\u003e 标记你回应的链接。此外 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-like-of%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20a%20%E2%80%9Clike%E2%80%9D%20(favorite%2C%20star)%20of.%20Optionally%20an%20embedded%20h-cite\"\u003eu-like-of\u003c/a\u003e、\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-repost-of%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20a%20%E2%80%9Crepost%E2%80%9D%20of.%20Optionally%20an%20embedded%20h-cite\"\u003eu-report-of\u003c/a\u003e 等可以用于标记不同的引用目的\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=dt-published%20-%20when%20the%20entry%20was%20published\"\u003edt-published\u003c/a\u003e 标记文章的发布日期\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=dt-updated%20-%20when%20the%20entry%20was%20updated\"\u003edt-updated\u003c/a\u003e 标记文章的更新日期\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n\u003cb\u003e关于 h-card\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\nh-card 是用来标记用户信息的,介绍一些我觉得比较有用的:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=p-name%20-%20The%20full/formatted%20name%20of%20the%20person%20or%20organization\"\u003ep-name\u003c/a\u003e 标记个人或组织的全称\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-email%20-%20email%20address\"\u003eu-email\u003c/a\u003e 标记邮箱,一般标记在 mailto 链接上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-logo%20-%20a%20logo%20representing%20the%20person%20or%20organization%20(e.g.%20a%20face%20icon)\"\u003eu-logo\u003c/a\u003e 标记你的 logo,一般标记在 \u003ccode\u003e\u0026lt;img\u0026gt;\u003c/code\u003e 标签上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-photo%20-%20a%20photo%20of%20the%20person%20or%20organization\"\u003eu-photo\u003c/a\u003e 标记你的头像,一般标记在 \u003ccode\u003e\u0026lt;img\u0026gt;\u003c/code\u003e 标签上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=u-url%20-%20home%20page%20or%20other%20URL%20representing%20the%20person%20or%20organization\"\u003eu-url\u003c/a\u003e 标记你的主页,一般标记在一个链接上\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://microformats.org/wiki/h-card#:~:text=p-note%20-%20additional%20notes\"\u003ep-note\u003c/a\u003e 标记额外信息,有人会用来写自我介绍\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n除了这些,还有标记地址、性别、国籍、出生日期、工作等,感兴趣可以自行探索。\n\u003c/p\u003e\n\n\u003cp\u003e\nh-card 可以结合 h-entry 的 p-author 用于标记文章的作者信息,\u003cb\u003e在这种场景下,h-entry 需要是 h-card 的父元素。\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n综上,一个相对完整的 microformats 标记是这样的:\n\u003c/p\u003e\n\n\n\u003cpre\u003e\u003ccode\u003e\u0026lt;\u003cspan\u003e!doctype\u003c/span\u003e html\u0026gt;\n\u0026lt;\u003cspan\u003emeta\u003c/span\u003e \u003cspan\u003echarset\u003c/span\u003e=\u003cspan\u003e\"utf-8\"\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan\u003etitle\u003c/span\u003e\u0026gt;\u003cspan\u003e\u003cspan\u003eHello World\u003c/span\u003e\u003c/span\u003e\u0026lt;/\u003cspan\u003etitle\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan\u003ebody\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ediv\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"h-entry\"\u003c/span\u003e\u0026gt; \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e注意 h-entry 是其他属性的父元素,包含了 h-card\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ediv\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"p-author h-card\"\u003c/span\u003e\u0026gt; \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e使用 h-card 结合 p-author 标记作者信息\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003eimg\u003c/span\u003e \u003cspan\u003esrc\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/images/aaronpk.jpg\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-photo\"\u003c/span\u003e \u003cspan\u003ewidth\u003c/span\u003e=\u003cspan\u003e\"40\"\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-url p-name\"\u003c/span\u003e\u0026gt;Aaron Parecki\u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ediv\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记引用的链接,表示回复\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e\u0026gt;in reply to: \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-in-reply-to\"\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003c/span\u003e\u0026gt;@aaronpk\u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记回复的内容\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"e-content\"\u003c/span\u003e\u0026gt;Trying out this guide to sending webmentions\u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u0026lt;\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记当前文章的 URL\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003ea\u003c/span\u003e \u003cspan\u003ehref\u003c/span\u003e=\u003cspan\u003e\"https://aaronpk.com/reply.html\"\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"u-url\"\u003c/span\u003e\u0026gt;\n \u003cspan\u003e\u0026lt;!-- \u003c/span\u003e\u003cspan\u003e标记当前文章的发布日期\u003c/span\u003e\u003cspan\u003e --\u0026gt;\u003c/span\u003e\n \u0026lt;\u003cspan\u003etime\u003c/span\u003e \u003cspan\u003eclass\u003c/span\u003e=\u003cspan\u003e\"dt-published\"\u003c/span\u003e \u003cspan\u003edatetime\u003c/span\u003e=\u003cspan\u003e\"2018-06-30T17:15:00-0700\"\u003c/span\u003e\u0026gt;July 30, 2018\u0026lt;/\u003cspan\u003etime\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ea\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ep\u003c/span\u003e\u0026gt;\n \u0026lt;/\u003cspan\u003ediv\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\n\n\u003cp\u003e\n具体如何标记,要看你博客中的 HTML 标记是如何排布的,在标记时注意层级关系就好。测试阶段可以多利用 \u003ca href=\"https://microformats.org/wiki/parsers\"\u003eMicroformats Parsers\u003c/a\u003e 解析你的文章,检查解析出来的内容是否符合需要。\n\u003c/p\u003e\n\n\u003cp\u003e\n都设置好之后就可以向集成了 Webmention 的网站发送通知了,你可以:\n\u003c/p\u003e\n\u003cul\u003e\u003cli\u003e找到引用文章的 Webmention 入口,填写你的文章 URL 并提交\u003c/li\u003e\n\u003cli\u003e自己构建 POST 请求,或用第三方服务,如 \u003ca href=\"https://telegraph.p3k.io/\"\u003eTelegraph\u003c/a\u003e 手动发送\u003c/li\u003e\n\u003cli\u003e考虑集成 \u003ca href=\"https://webmention.app/\"\u003ewebmention.app\u003c/a\u003e 等实现自动发送\u003c/li\u003e\n\u003c/ul\u003e\u003cp\u003e\n一般发送之后都会有响应,如果你的 Webmention 没有展示出来,可以基于返回信息进行问题排查。\n\u003c/p\u003e\n\n\n\n\n\u003ch2\u003e一些问题\u003c/h2\u003e\n\n\n\u003ch3\u003e常见问题\u003c/h3\u003e\n\u003cp\u003e\n大部分疑惑 \u003ca href=\"https://indieweb.org/Webmention-faq\"\u003eWebmention-faq | IndieWeb\u003c/a\u003e 中都有解答。\n\u003c/p\u003e\n\n\u003cp\u003e\n分享一些比较常见的问题:\n\u003c/p\u003e\n\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Do_webmentions_work_only_when_both_sites_use_webmentions?\"\u003eDo webmentions work only when both sites use webmentions?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#How_do_you_know_if_a_website_uses_webmentions?\"\u003eHow do you know if a website uses webmentions?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Which_links_should_webmentions_be_sent_to\"\u003eWhich links should webmentions be sent to\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://indieweb.org/Webmention-faq#Should_webmentions_be_sent_for_removals\"\u003eShould webmentions be sent for removals\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003e关于 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=u-in-reply-to%20-%20the%20URL%20which%20the%20h-entry%20is%20considered%20reply%20to%20(i.e.%20doesn%E2%80%99t%20make%20sense%20without%20context%2C%20could%20show%20up%20in%20comment%20thread)%2C%20optionally%20an%20embedded%20h-cite%20(reply-context)%20(example)\"\u003eu-in-reply-to\u003c/a\u003e 的使用\u003c/h3\u003e\n\u003cp\u003e\n\u003ccode\u003eu-in-reply-to\u003c/code\u003e 用于标记 h-entry 中要回复的链接,应该结合 \u003ccode\u003ee-content\u003c/code\u003e 标记回应的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果只是引用了一些链接,并没有对于这些链接的回应,不需要用 \u003ccode\u003eu-in-reply-to\u003c/code\u003e 标记,直接发送 Webmention 就好了。\n\u003c/p\u003e\n\n\n\n\u003ch3\u003e关于 \u003ca href=\"https://microformats.org/wiki/h-entry\"\u003eh-entry\u003c/a\u003e 的使用\u003c/h3\u003e\n\u003cp\u003e\n尽管可以设置多个 h-entry,但我觉得一篇文章一个 h-entry 就够了。\n\u003c/p\u003e\n\n\u003cp\u003e\n原因是 h-entry 往往需要指定文章标题、作者、发布和更新时间、内容等,这和一篇文章的内容是刚好对应上的。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果标记多个 h-entry,比较难保证每个 h-entry 都有这些信息,尽管 \u003ca href=\"https://microformats.org/wiki/h-entry#:~:text=the%20%22datetime%22%20property.-,what%20is%20the%20bare%20minimum%20list%20of%20required%20properties%20on%20an,a%20nested%20h-card%20with%20author%20details%20like%20name%2C%20photo%2C%20url.,-Examples%20in%20the\"\u003eh-entry 不要求包含任一属性\u003c/a\u003e。\n\u003c/p\u003e\n\n\u003cp\u003e\n我的建议是:\n\u003c/p\u003e\n\n\u003cul\u003e\u003cli\u003eh-entry 设置在包含文章内容、作者信息、发布日期等的父元素上\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\ne-content 设置在包含整篇文章内容的元素上\n\u003c/p\u003e\n\n\u003cp\u003e\n好处是,只要在文章中的链接都能被发现,不需要额外再标记什么。缺点是,e-content 标记的内容可能太多,导致实际回复的部分被淹没其中。\n\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch3\u003ewebmention.io 的 target 需要完全匹配\u003c/h3\u003e\n\u003cp\u003e\n见 \u003ca href=\"https://github.com/aaronpk/webmention.io/issues/229#issuecomment-3602563563\"\u003eWhen URL has hash,webmention.io'a API not reponse data #229\u003c/a\u003e。\n\u003c/p\u003e\n\n\u003cp\u003e\n有的 webmention 的发送时的 URL 是 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,通过 webmention.io 的 \u003ca href=\"https://github.com/aaronpk/webmention.io?tab=readme-ov-file#api\"\u003eAPI\u003c/a\u003e,target 参数设置为 \u003ccode\u003ehttps://domain/page.html\u003c/code\u003e 是无法获取到数据的,需要将 target 设置为 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,完全匹配才行,因为目前存储的就是完整的 URL。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果 target 是 \u003ccode\u003ehttps://domain/page.html#abc\u003c/code\u003e ,注意需要将 \u003ccode\u003e#\u003c/code\u003e \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent\"\u003e转义\u003c/a\u003e 成 \u003ccode\u003e%23\u003c/code\u003e 。\n\u003c/p\u003e\n\u003cp\u003e\n我目前的处理方法是用 \u003ca href=\"https://github.com/aaronpk/webmention.io?tab=readme-ov-file#find-all-links-to-your-domain\"\u003e基于域名获取所有数据的 API\u003c/a\u003e 先获取所有的数据,然后基于页面的 URL 进行过滤。\n\u003c/p\u003e\n\n\n\n\u003ch3\u003e发送了 webmention 但是没有显示出来\u003c/h3\u003e\n\u003cp\u003e\n一种可能是,webmention 要求源页面中包含目标页面的链接,而有的源页面是由 JS 动态渲染的,不是静态的,导致 webmention 无法从源页面找到目标页面的链接,而认为源页面没有发送 webmention。\n\u003c/p\u003e\n\n\u003cp\u003e\n排查的方法是,在浏览器中查看网络请求,找到源页面返回的内容,搜索一下内容中是否包含目标页面的链接。\n\u003c/p\u003e\n\n\u003cp\u003e\n也可能是网站显示的问题,可以尝试联系作者。\n\u003c/p\u003e\n\n\n\n\n\u003ch2\u003e写在最后\u003c/h2\u003e\n\u003cp\u003e\n以为接入挺简单的,但实际做还是折腾了两天,果真是「纸上得来终觉浅,绝知此事要躬行」呀。\n\u003c/p\u003e\n\n\u003cp\u003e\n如果你链接了我的文章,欢迎你向我发送 Webmention,这样就建立了文章之间的链接。一方面我可以看看别人引用时的评论;另一方面,其他读者也可以通过 Webmention 知道你的文章。\n\u003c/p\u003e\n\n\u003cp\u003e\n我认为这是一件共赢的事,你引用了我的链接,帮我推广了给更多人;而你向引用的文章发送 Webmention,也能帮忙推广你的内容。\n\u003c/p\u003e\n\n\u003cp\u003e\n何乐而不为?\n\u003c/p\u003e\n\n\n\n\u003ch2\u003e其他参考文章\u003c/h2\u003e\n\u003cul\u003e\u003cli\u003e\u003ca href=\"https://jason-memo.dev/posts/webmention/\"\u003e透過 webmention 來搜集 blog 的社群迴響\u003c/a\u003e by Jason Chen\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://blog.xiang578.com/note/641ea60f-a31e-4979-9327-c50509c146e3.html\"\u003eWebmention 实现参考\u003c/a\u003e by Runye\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.owenyoung.com/en/blog/indieweb/\"\u003eNow, I'm in IndieWeb?\u003c/a\u003e by Owen Young\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://blog.cytrogen.icu/posts/1de\"\u003e在 Hexo 项目中添加 Webmention\u003c/a\u003e by Cytrogen\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.geedea.pro/article/webmention/\"\u003eWebmention 简明指南\u003c/a\u003e by Eltrac\u003c/li\u003e\n\u003c/ul\u003e",
- "text": "给博客添加 Webmention\n目录\n\n什么是 Webmention\n为什么接入 Webmention\n如何接入 Webmention\n一些问题\n写在最后\n其他参考文章\n\n???? The Great Escape Of Our Time - 椅子乐团 The Chairs\n\n\n什么是 Webmention\n\n\nWebmention 是一种通知,表明一个 URL 链接到另一个 URL。\n\n\n\n例如,Alice 在她的博客上写了一篇有趣的帖子。随后 Bob 在自己的网站上写了一篇回复她的帖子,并链接回 Alice 的原始帖子。\nBob 的发布软件向 Alice 发送一个 Webmention,通知她的文章被回复了,\nAlice 的软件可以将该回复显示为原始帖子上的评论。\n\n\n\nSource\n\n\n\n\nWebmention 和评论差不多,只是它的门槛相对高一点,需要你写一篇文章,并链接到你想评论的文章。\n(或者在社交媒体如 BlueSky、Mastodon 上发一个帖子,引用文章的链接)\n\n\n\n如果对方支持了 Webmention,你发送 Webmention 通知后,对方就会将你的内容显示出来。\n\n\nWebmention 的大致流程\n\n图1 Webmention 的大致流程,参考 https://www.w3.org/TR/webmention/#protocol-summary\n\n\n为什么接入 Webmention\n\n\n实现跨站点的对话。当你链接到某个网站时,你可以发送一个 Webmention 来通知它。如果该网站支持 Webmention,那么该网站可能会将你的帖子显示为评论、赞或其他回应,就这样,你就实现了从一个站点到另一个站点的对话!\n\n\n\nSource\n\n\n\n\n我觉得 Webmention 和集成在博客中的评论系统是类似的。\n\n\n\n如果你要回应一篇文章,通过 Webmention,你需要写一篇文章链接到这篇文章,并发送一个 Webmention 通知。通过如 Bridgy 之类的服务,也可以收集社交网络上(Blusky、Mastodon 等)关于文章的回应,例如点赞、转发等。\n\n\n\n但我觉得并没有比集成于博客的评论系统更方便。\n\n\n\n从数据层面看,除非自己买服务器搭建 Webmention,否则用第三方提供的服务,数据依然不在自己的手上。\n\n\n\n所以我为什么要接入 Webmention?\n\n\n\n最开始是在 我想让自己说话不那么“端着” | Owen Young 中了解到 Webmention,当时觉得有些麻烦。\n\n\n\n最近网上冲浪的时候,看到不少博客都有集成 Webmention,然后了解了一下 webmention.io 的使用,看起来不麻烦,就想着集成看看。\n\n\n\n非要找个理由的话,就是折腾一下,好玩吧。\n\n\n\n\n如何接入 Webmention\n\n如果自己搭建的话,可以参照 Webmention 规范 实现;或者找现成的工具,你可以在 Webmention | IndieWeb 找到很多工具和服务。\n\n\n\n我目前实现很简单,接收依赖 webmention.io 提供的服务,需要自己编写一点 脚本 调用 API;发送通过手动触发;麻烦一些的地方是给博客添加 microformats 。\n\n\n\n作为接收方\n\n接收我使用 webmention.io 提供的服务,按照 How to Set Up Your Website for IndieLogin.com 的说明进行设置。\n\n\n\n我用 GitHub 进行验证,需要在 GitHub Profile 中包含我的网站,同时在网站添加一个链接。\n\n\n\n\n\n图2 我的 GitHub Profile 页面,我把网站的地址添加到了 Profile 中\n\u003chead\u003e\n \u003c!-- 省略其他内容 --\u003e\n \u003clink href=\"https://github.com/spike-leung\" rel=\"me\"\u003e\n \u003c!-- 省略其他内容 --\u003e\n\u003c/head\u003e\n\n\n\n\n这样就能通过 webmention.io 的验证了。\n\n\n\n接下来按照 webmention.io 提供的 API 获取 Webmentions 的数量和内容,需要在页面上添加 HTML 元素,写 一些 JS 代码 调用 API 渲染数据(也可以用 webmention.js),再写点 CSS 优化一下样式。\n\n\n\n如果你打算渲染 Webmentions 返回的 HTML,需要注意 Cross-site scripting (XSS) 攻击。\n\n\n防止 XSS 攻击\n防止 XSS 攻击,Trusted Types API 看起来不错,可惜浏览器支持度不够。\n\n\n\n防御 XSS 主要从两方面入手:\n\n净化 (sanitize) 用户输入的内容。可以使用 DOMPurify 处理。\n使用 Content Security Policy (CSP) 限制执行。Netlify 有插件支持,倒是方便了许多。要注意的是,当开启了 CSP,一些行内的脚本,如写在元素上的 onclick、 onchange 等会被阻止执行,需要将他们挪动到 JS 文件里。\n\n也可以期待一下 Element: setHTML() method 被广泛支持,它提供了一种 XSS 安全的方法用于插入 HTML 内容到页面中。\n\n\n搭建好之后,可以用 Webmention Rocks! 提供的服务进行测试。\n\n\n\n至于查看 Webmentions 也有几种方法:\n\n到对应的页面下看\n订阅 webmention.io 提供的 Mentions Feed\n使用 webmention.io 提供的 Web Hook 通知自己\n到 webmention.io 的 Dashbaord 查看\n作为发送方\n\n作为发送方,你只需要在你的文章中包含对方的链接,就可以向对方发送 Webmention 了。\n\n\n\n但是如果你想让你发送的内容更丰富一些,就需要通过 microformats 标记网站信息,如用户名、头像、内容、你要提及的链接等,从而让 Webmention 解析展示。\n\n\n\n按理说只要包含了对方链接,对方就能收到 Webmention。\n\n\n\n但我发送后却收到了「The Microformats at the source URL do not contain a link to the target URL.」的错误提示。\n\n\n\n可能是因为我使用 microformats 标记了内容,此时需要确保 microformats 解析后的内容中,包含对方的 URL。\n\n\n最主要的标记是 h-card 和 h-entry,h-card 标记用户信息;\nh-entry 标记内容信息,标记的部分会作为 Webmention 的内容呈现。\n\n\n\n关于 h-card 和 h-entry 的作用,推荐看 Sending your First Webmention from Scratch,文章循序渐进地引导你添加相应的标记,并且有对应的示例,同时文章本身也可以用来测试 Webmention 的发送。\n\n\n\nmicroformats 这些标记,可以和 HTML 做类比,它也是有层级关系的,最终会解析成一个 JSON 的树形结构。在你测试的时候,可以从 Microformats Parsers 找一个 parser 检查你的文章解析出来的内容。\n\n\n\n关于 h-entry\n\n\n\nwhat is the bare minimum list of required properties on an h-entry 中回答道,没有任何 h-entry 的属性是强制要求的。\n\n\n\n但推荐至少包含:\n\ne-content 标记文章内容,被标记的内容会作为 Webmention 的内容被发送\np-name 标记文章标题\np-author 标记作者信息,一般会和 h-card 结合使用\n\n一些我建议加上的:\n\nu-in-reply-to 标记你回应的链接。此外 u-like-of、u-report-of 等可以用于标记不同的引用目的\ndt-published 标记文章的发布日期\ndt-updated 标记文章的更新日期\n\n关于 h-card\n\n\n\nh-card 是用来标记用户信息的,介绍一些我觉得比较有用的:\n\np-name 标记个人或组织的全称\nu-email 标记邮箱,一般标记在 mailto 链接上\nu-logo 标记你的 logo,一般标记在 \u003cimg\u003e 标签上\nu-photo 标记你的头像,一般标记在 \u003cimg\u003e 标签上\nu-url 标记你的主页,一般标记在一个链接上\np-note 标记额外信息,有人会用来写自我介绍\n\n除了这些,还有标记地址、性别、国籍、出生日期、工作等,感兴趣可以自行探索。\n\n\n\nh-card 可以结合 h-entry 的 p-author 用于标记文章的作者信息,在这种场景下,h-entry 需要是 h-card 的父元素。\n\n\n\n综上,一个相对完整的 microformats 标记是这样的:\n\n\n\n\u003c!doctype html\u003e\n\u003cmeta charset=\"utf-8\"\u003e\n\u003ctitle\u003eHello World\u003c/title\u003e\n\u003cbody\u003e\n \u003cdiv class=\"h-entry\"\u003e \u003c!-- 注意 h-entry 是其他属性的父元素,包含了 h-card --\u003e\n \u003cdiv class=\"p-author h-card\"\u003e \u003c!-- 使用 h-card 结合 p-author 标记作者信息 --\u003e\n \u003cimg src=\"https://aaronpk.com/images/aaronpk.jpg\" class=\"u-photo\" width=\"40\"\u003e\n \u003ca href=\"https://aaronpk.com/\" class=\"u-url p-name\"\u003eAaron Parecki\u003c/a\u003e\n \u003c/div\u003e\n \u003c!-- 标记引用的链接,表示回复 --\u003e\n \u003cp\u003ein reply to: \u003ca class=\"u-in-reply-to\" href=\"https://aaronparecki.com/2018/06/30/11/your-first-webmention\"\u003e@aaronpk\u003c/a\u003e\u003c/p\u003e\n \u003c!-- 标记回复的内容 --\u003e\n \u003cp class=\"e-content\"\u003eTrying out this guide to sending webmentions\u003c/p\u003e\n \u003cp\u003e\n \u003c!-- 标记当前文章的 URL --\u003e\n \u003ca href=\"https://aaronpk.com/reply.html\" class=\"u-url\"\u003e\n \u003c!-- 标记当前文章的发布日期 --\u003e\n \u003ctime class=\"dt-published\" datetime=\"2018-06-30T17:15:00-0700\"\u003eJuly 30, 2018\u003c/time\u003e\n \u003c/a\u003e\n \u003c/p\u003e\n \u003c/div\u003e\n\u003c/body\u003e\n\n\n\n\n具体如何标记,要看你博客中的 HTML 标记是如何排布的,在标记时注意层级关系就好。测试阶段可以多利用 Microformats Parsers 解析你的文章,检查解析出来的内容是否符合需要。\n\n\n\n都设置好之后就可以向集成了 Webmention 的网站发送通知了,你可以:\n\n找到引用文章的 Webmention 入口,填写你的文章 URL 并提交\n自己构建 POST 请求,或用第三方服务,如 Telegraph 手动发送\n考虑集成 webmention.app 等实现自动发送\n\n一般发送之后都会有响应,如果你的 Webmention 没有展示出来,可以基于返回信息进行问题排查。\n\n\n\n\n\n一些问题\n\n\n常见问题\n\n大部分疑惑 Webmention-faq | IndieWeb 中都有解答。\n\n\n\n分享一些比较常见的问题:\n\n\nDo webmentions work only when both sites use webmentions?\nHow do you know if a website uses webmentions?\nWhich links should webmentions be sent to\nShould webmentions be sent for removals\n关于 u-in-reply-to 的使用\n\nu-in-reply-to 用于标记 h-entry 中要回复的链接,应该结合 e-content 标记回应的内容。\n\n\n\n如果只是引用了一些链接,并没有对于这些链接的回应,不需要用 u-in-reply-to 标记,直接发送 Webmention 就好了。\n\n\n\n\n关于 h-entry 的使用\n\n尽管可以设置多个 h-entry,但我觉得一篇文章一个 h-entry 就够了。\n\n\n\n原因是 h-entry 往往需要指定文章标题、作者、发布和更新时间、内容等,这和一篇文章的内容是刚好对应上的。\n\n\n\n如果标记多个 h-entry,比较难保证每个 h-entry 都有这些信息,尽管 h-entry 不要求包含任一属性。\n\n\n\n我的建议是:\n\n\nh-entry 设置在包含文章内容、作者信息、发布日期等的父元素上\n\ne-content 设置在包含整篇文章内容的元素上\n\n\n\n好处是,只要在文章中的链接都能被发现,不需要额外再标记什么。缺点是,e-content 标记的内容可能太多,导致实际回复的部分被淹没其中。\n\nwebmention.io 的 target 需要完全匹配\n\n见 When URL has hash,webmention.io'a API not reponse data #229。\n\n\n\n有的 webmention 的发送时的 URL 是 https://domain/page.html#abc ,通过 webmention.io 的 API,target 参数设置为 https://domain/page.html 是无法获取到数据的,需要将 target 设置为 https://domain/page.html#abc ,完全匹配才行,因为目前存储的就是完整的 URL。\n\n\n\n如果 target 是 https://domain/page.html#abc ,注意需要将 # 转义 成 %23 。\n\n\n我目前的处理方法是用 基于域名获取所有数据的 API 先获取所有的数据,然后基于页面的 URL 进行过滤。\n\n\n\n\n发送了 webmention 但是没有显示出来\n\n一种可能是,webmention 要求源页面中包含目标页面的链接,而有的源页面是由 JS 动态渲染的,不是静态的,导致 webmention 无法从源页面找到目标页面的链接,而认为源页面没有发送 webmention。\n\n\n\n排查的方法是,在浏览器中查看网络请求,找到源页面返回的内容,搜索一下内容中是否包含目标页面的链接。\n\n\n\n也可能是网站显示的问题,可以尝试联系作者。\n\n\n\n\n\n写在最后\n\n以为接入挺简单的,但实际做还是折腾了两天,果真是「纸上得来终觉浅,绝知此事要躬行」呀。\n\n\n\n如果你链接了我的文章,欢迎你向我发送 Webmention,这样就建立了文章之间的链接。一方面我可以看看别人引用时的评论;另一方面,其他读者也可以通过 Webmention 知道你的文章。\n\n\n\n我认为这是一件共赢的事,你引用了我的链接,帮我推广了给更多人;而你向引用的文章发送 Webmention,也能帮忙推广你的内容。\n\n\n\n何乐而不为?\n\n\n\n\n其他参考文章\n透過 webmention 來搜集 blog 的社群迴響 by Jason Chen\nWebmention 实现参考 by Runye\nNow, I'm in IndieWeb? by Owen Young\n在 Hexo 项目中添加 Webmention by Cytrogen\nWebmention 简明指南 by Eltrac"
- },
- "published": "2025-09-25T21:24:00",
- "received": "2026-03-10T17:08:32Z",
- "source": "https://taxodium.ink/add-webmention-to-blog.html",
- "type": "mention-of",
- "url": "https://taxodium.ink/add-webmention-to-blog.html"
- },
- {
- "author": {
"name": "Eltrac :neocat_laptop:",
"photo": "https://avatars.webmention.io/akk-media.eltr.ac/96fdded4db077fd77188a2ca1427f357b0fda90f141c58c9bac3e1706c050c2a.jpg",
"type": "card",
@@ -454,15 +584,12 @@
"type": "card",
"url": "https://mastodon.social/@J_sky"
},
- "content": {
- "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 文章分析的真是细致哇,收藏了,过几天试试看。\u003c/p\u003e",
- "text": "@eltrac 文章分析的真是细致哇,收藏了,过几天试试看。"
- },
- "published": "2026-03-11T13:27:14+00:00",
+ "content": null,
+ "published": null,
"received": "2026-03-11T13:34:14Z",
- "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B49J2xyrnOIitllQ8G",
- "type": "in-reply-to",
- "url": "https://mastodon.social/@J_sky/116210770572306766"
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B38w5506lDT25A15KS",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B47Na8WhcQVAf7k6bI#favorited-by-B38w5506lDT25A15KS"
},
{
"author": {
@@ -471,12 +598,15 @@
"type": "card",
"url": "https://mastodon.social/@J_sky"
},
- "content": null,
- "published": null,
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 文章分析的真是细致哇,收藏了,过几天试试看。\u003c/p\u003e",
+ "text": "@eltrac 文章分析的真是细致哇,收藏了,过几天试试看。"
+ },
+ "published": "2026-03-11T13:27:14+00:00",
"received": "2026-03-11T13:34:14Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B38w5506lDT25A15KS",
- "type": "like-of",
- "url": "https://akk.eltr.ac/notice/B47Na8WhcQVAf7k6bI#favorited-by-B38w5506lDT25A15KS"
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B47Na8WhcQVAf7k6bI/B49J2xyrnOIitllQ8G",
+ "type": "in-reply-to",
+ "url": "https://mastodon.social/@J_sky/116210770572306766"
},
{
"author": {
@@ -911,12 +1041,15 @@
"type": "card",
"url": "https://mastodon.social/@J_sky"
},
- "content": null,
- "published": null,
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 还好哲学家大多不写代码,不然写的代码和文档也不知道别人能不能看懂。\u003c/p\u003e",
+ "text": "@eltrac 还好哲学家大多不写代码,不然写的代码和文档也不知道别人能不能看懂。"
+ },
+ "published": "2026-02-11T02:26:45+00:00",
"received": "2026-02-11T02:53:56Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3BPNmGpuQFSTr1r04/B38w5506lDT25A15KS",
- "type": "like-of",
- "url": "https://akk.eltr.ac/notice/B3BPNmGpuQFSTr1r04#favorited-by-B38w5506lDT25A15KS"
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B3BPNmGpuQFSTr1r04/B3CJiHwbS3xvwIvEC8",
+ "type": "in-reply-to",
+ "url": "https://mastodon.social/@J_sky/116049628747974714"
},
{
"author": {
@@ -925,15 +1058,12 @@
"type": "card",
"url": "https://mastodon.social/@J_sky"
},
- "content": {
- "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e 还好哲学家大多不写代码,不然写的代码和文档也不知道别人能不能看懂。\u003c/p\u003e",
- "text": "@eltrac 还好哲学家大多不写代码,不然写的代码和文档也不知道别人能不能看懂。"
- },
- "published": "2026-02-11T02:26:45+00:00",
+ "content": null,
+ "published": null,
"received": "2026-02-11T02:53:56Z",
- "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B3BPNmGpuQFSTr1r04/B3CJiHwbS3xvwIvEC8",
- "type": "in-reply-to",
- "url": "https://mastodon.social/@J_sky/116049628747974714"
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3BPNmGpuQFSTr1r04/B38w5506lDT25A15KS",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B3BPNmGpuQFSTr1r04#favorited-by-B38w5506lDT25A15KS"
},
{
"author": {
@@ -1522,31 +1652,31 @@
"/glossary/": [
{
"author": {
- "name": "KipJayChou ⁂ :neocat_cofe:",
- "photo": "https://avatars.webmention.io/files.mstdn.feddit.social/b3a5ebdc7764c92d0a28a39ee05451f98685bd5f10185dc981856443952aa13c.png",
+ "name": "活泼可爱小僵丝",
+ "photo": "https://darkwitch.net/system/accounts/avatars/111/296/789/771/189/022/original/11a5cec8541aa8aa.webp",
"type": "card",
- "url": "https://mstdn.feddit.social/@admin"
+ "url": "https://darkwitch.net/@zombiegpt"
},
"content": null,
"published": null,
"received": "2026-02-20T08:11:41Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3VQog0Hh9VD8du4dE/B2SrMy0eBj7rdlvD3A",
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3VQog0Hh9VD8du4dE/B2TgLIrInNMdO1VyPg",
"type": "like-of",
- "url": "https://akk.eltr.ac/notice/B3VQog0Hh9VD8du4dE#favorited-by-B2SrMy0eBj7rdlvD3A"
+ "url": "https://akk.eltr.ac/notice/B3VQog0Hh9VD8du4dE#favorited-by-B2TgLIrInNMdO1VyPg"
},
{
"author": {
- "name": "活泼可爱小僵丝",
- "photo": "https://darkwitch.net/system/accounts/avatars/111/296/789/771/189/022/original/11a5cec8541aa8aa.webp",
+ "name": "KipJayChou ⁂ :neocat_cofe:",
+ "photo": "https://avatars.webmention.io/files.mstdn.feddit.social/b3a5ebdc7764c92d0a28a39ee05451f98685bd5f10185dc981856443952aa13c.png",
"type": "card",
- "url": "https://darkwitch.net/@zombiegpt"
+ "url": "https://mstdn.feddit.social/@admin"
},
"content": null,
"published": null,
"received": "2026-02-20T08:11:41Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3VQog0Hh9VD8du4dE/B2TgLIrInNMdO1VyPg",
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B3VQog0Hh9VD8du4dE/B2SrMy0eBj7rdlvD3A",
"type": "like-of",
- "url": "https://akk.eltr.ac/notice/B3VQog0Hh9VD8du4dE#favorited-by-B2TgLIrInNMdO1VyPg"
+ "url": "https://akk.eltr.ac/notice/B3VQog0Hh9VD8du4dE#favorited-by-B2SrMy0eBj7rdlvD3A"
},
{
"author": {
@@ -2671,12 +2801,15 @@
"type": "card",
"url": "https://rex.cat/@lok"
},
- "content": null,
- "published": null,
+ "content": {
+ "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e http.cat 好好玩,感谢 \u003cimg alt=\"happy\" src=\"https://rex.cat/fileserver/01RE9Y7N8ZQW9T8ZFBJRCNB38F/emoji/original/01KERSRBGVZQ4SN7R3RTRPYFAG.gif\" /\u003e\u003c/p\u003e",
+ "text": "@eltrac http.cat 好好玩,感谢"
+ },
+ "published": "2026-02-04T03:32:58+00:00",
"received": "2026-02-04T03:40:42Z",
- "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B2taFnPZD7Zz1WuD7w/B2SrMficC20SudLYRc",
- "type": "like-of",
- "url": "https://akk.eltr.ac/notice/B2taFnPZD7Zz1WuD7w#favorited-by-B2SrMficC20SudLYRc"
+ "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B2taFnPZD7Zz1WuD7w/B2xu1UGkMMXjJg4fEO",
+ "type": "in-reply-to",
+ "url": "https://rex.cat/@lok/statuses/01KGKBBPKYZR77PR5M927VNC3M"
},
{
"author": {
@@ -2685,15 +2818,12 @@
"type": "card",
"url": "https://rex.cat/@lok"
},
- "content": {
- "html": "\u003cp\u003e\u003cspan class=\"h-card\"\u003e\u003ca href=\"https://akk.eltr.ac/users/eltrac\" class=\"u-url\"\u003e@\u003cspan\u003eeltrac\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e http.cat 好好玩,感谢 \u003cimg alt=\"happy\" src=\"https://rex.cat/fileserver/01RE9Y7N8ZQW9T8ZFBJRCNB38F/emoji/original/01KERSRBGVZQ4SN7R3RTRPYFAG.gif\" /\u003e\u003c/p\u003e",
- "text": "@eltrac http.cat 好好玩,感谢"
- },
- "published": "2026-02-04T03:32:58+00:00",
+ "content": null,
+ "published": null,
"received": "2026-02-04T03:40:42Z",
- "source": "https://brid.gy/comment/mastodon/@eltrac@akk.eltr.ac/B2taFnPZD7Zz1WuD7w/B2xu1UGkMMXjJg4fEO",
- "type": "in-reply-to",
- "url": "https://rex.cat/@lok/statuses/01KGKBBPKYZR77PR5M927VNC3M"
+ "source": "https://brid.gy/like/mastodon/@eltrac@akk.eltr.ac/B2taFnPZD7Zz1WuD7w/B2SrMficC20SudLYRc",
+ "type": "like-of",
+ "url": "https://akk.eltr.ac/notice/B2taFnPZD7Zz1WuD7w#favorited-by-B2SrMficC20SudLYRc"
}
],
"/posts/weekly/67/": [