@chrisburnell/eleventy-cache-webmentions 0.1.11 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +4 -0
- package/eleventy-cache-webmentions.js +59 -41
- package/package.json +2 -3
package/.prettierrc
ADDED
|
@@ -3,11 +3,6 @@ const sanitizeHTML = require("sanitize-html")
|
|
|
3
3
|
const uniqBy = require("lodash/uniqBy")
|
|
4
4
|
const { AssetCache } = require("@11ty/eleventy-fetch")
|
|
5
5
|
|
|
6
|
-
// Load .env variables with dotenv
|
|
7
|
-
require("dotenv").config()
|
|
8
|
-
|
|
9
|
-
const TOKEN = process.env.WEBMENTION_IO_TOKEN
|
|
10
|
-
|
|
11
6
|
const absoluteURL = (url, domain) => {
|
|
12
7
|
try {
|
|
13
8
|
return new URL(url, domain).toString()
|
|
@@ -42,10 +37,30 @@ const epoch = (value) => {
|
|
|
42
37
|
return new Date(value).getTime()
|
|
43
38
|
}
|
|
44
39
|
|
|
40
|
+
const getPublished = (webmention) => {
|
|
41
|
+
return webmention["wm-received"] || webmention?.["data"]["published"] || webmention["verified_date"] || webmention["published"]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const getContent = (webmention) => {
|
|
45
|
+
return webmention?.["content"]["html"] || webmention["content"] || webmention?.["data"]["content"]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const getSource = (webmention) => {
|
|
49
|
+
return webmention["url"] || webmention?.["data"]["url"] || webmention["wm-source"] || webmention["source"]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const getTarget = (webmention) => {
|
|
53
|
+
return webmention["wm-target"] || webmention["target"]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const getType = (webmention) => {
|
|
57
|
+
return webmention["wm-property"] || webmention?.["activity"]["type"] || webmention["type"]
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
module.exports = (eleventyConfig, options = {}) => {
|
|
46
61
|
options = Object.assign(
|
|
47
62
|
{
|
|
48
|
-
|
|
63
|
+
uniqueKey: "webmentions",
|
|
49
64
|
allowedHTML: {
|
|
50
65
|
allowedTags: ["b", "i", "em", "strong", "a"],
|
|
51
66
|
allowedAttributes: {
|
|
@@ -60,14 +75,10 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
60
75
|
)
|
|
61
76
|
|
|
62
77
|
const fetchWebmentions = async () => {
|
|
63
|
-
let asset = new AssetCache(options.uniqueKey
|
|
78
|
+
let asset = new AssetCache(options.uniqueKey)
|
|
64
79
|
asset.ensureDir()
|
|
65
80
|
|
|
66
|
-
let webmentions =
|
|
67
|
-
type: "feed",
|
|
68
|
-
name: "Webmentions",
|
|
69
|
-
children: [],
|
|
70
|
-
}
|
|
81
|
+
let webmentions = []
|
|
71
82
|
|
|
72
83
|
// If there is a cached file at all, grab its contents now
|
|
73
84
|
if (asset.isCacheValid("9001y")) {
|
|
@@ -75,25 +86,27 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
// If there is a cached file but it is outside of expiry, fetch fresh
|
|
78
|
-
// results since the most recent
|
|
89
|
+
// results since the most recent webmention
|
|
79
90
|
if (!asset.isCacheValid(options.duration)) {
|
|
80
|
-
const since = webmentions.
|
|
81
|
-
const url =
|
|
91
|
+
const since = webmentions.length ? getPublished(webmentions[0]) : false
|
|
92
|
+
const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
|
|
82
93
|
await fetch(url)
|
|
83
94
|
.then(async (response) => {
|
|
84
95
|
if (response.ok) {
|
|
85
96
|
const feed = await response.json()
|
|
86
|
-
if (feed.
|
|
87
|
-
|
|
97
|
+
if (feed[options.key].length) {
|
|
98
|
+
webmentions = uniqBy([...feed[options.key], ...webmentions], (entry) => {
|
|
99
|
+
return getSource(entry)
|
|
100
|
+
})
|
|
101
|
+
console.log(`[${hostname(options.domain)}] ${feed[options.key].length} new Webmentions fetched into cache.`)
|
|
88
102
|
}
|
|
89
|
-
webmentions.children = [...feed.children, ...webmentions.children]
|
|
90
103
|
await asset.save(webmentions, "json")
|
|
91
104
|
return webmentions
|
|
92
105
|
}
|
|
93
106
|
return Promise.reject(response)
|
|
94
107
|
})
|
|
95
108
|
.catch((error) => {
|
|
96
|
-
console.log(`[${hostname(options.domain)}] Something went wrong with your request to
|
|
109
|
+
console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
|
|
97
110
|
})
|
|
98
111
|
}
|
|
99
112
|
|
|
@@ -105,9 +118,9 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
105
118
|
let webmentions = {}
|
|
106
119
|
|
|
107
120
|
// Sort Webmentions into groups by target
|
|
108
|
-
rawWebmentions.
|
|
121
|
+
rawWebmentions.forEach((webmention) => {
|
|
109
122
|
// Get the target of the Webmention and fix it up
|
|
110
|
-
let url = baseUrl(fixUrl(webmention
|
|
123
|
+
let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
|
|
111
124
|
|
|
112
125
|
if (!webmentions[url]) {
|
|
113
126
|
webmentions[url] = []
|
|
@@ -116,10 +129,10 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
116
129
|
webmentions[url].push(webmention)
|
|
117
130
|
})
|
|
118
131
|
|
|
119
|
-
// Sort Webmentions in groups by url and remove duplicates by
|
|
132
|
+
// Sort Webmentions in groups by url and remove duplicates by `url`
|
|
120
133
|
for (let url in webmentions) {
|
|
121
|
-
webmentions[url] = uniqBy(webmentions[url], (
|
|
122
|
-
return
|
|
134
|
+
webmentions[url] = uniqBy(webmentions[url], (entry) => {
|
|
135
|
+
return getSource(entry)
|
|
123
136
|
})
|
|
124
137
|
}
|
|
125
138
|
|
|
@@ -137,31 +150,26 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
137
150
|
const results = webmentions[url]
|
|
138
151
|
// filter webmentions by allowed response post types
|
|
139
152
|
.filter((entry) => {
|
|
140
|
-
return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(entry
|
|
141
|
-
})
|
|
142
|
-
// remove webmentions without an author name
|
|
143
|
-
.filter((entry) => {
|
|
144
|
-
const { author } = entry
|
|
145
|
-
return !!author && !!author.name
|
|
153
|
+
return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
|
|
146
154
|
})
|
|
147
|
-
// sanitize content of webmentions
|
|
155
|
+
// sanitize content of webmentions against HTML limit
|
|
148
156
|
.map((entry) => {
|
|
149
|
-
if (!("content" in entry)) {
|
|
157
|
+
if (!("content" in entry) || !("data" in entry)) {
|
|
150
158
|
return entry
|
|
151
159
|
}
|
|
152
|
-
const
|
|
160
|
+
const html = getContent(entry)
|
|
153
161
|
if (html && html.length > options.maximumHtmlLength) {
|
|
154
|
-
entry.content
|
|
162
|
+
entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
|
|
155
163
|
} else if (Object.keys(options.allowedHTML).length) {
|
|
156
|
-
entry.content
|
|
164
|
+
entry.content = sanitizeHTML(html, options.allowedHTML)
|
|
157
165
|
} else {
|
|
158
|
-
entry.content
|
|
166
|
+
entry.content = html
|
|
159
167
|
}
|
|
160
168
|
return entry
|
|
161
169
|
})
|
|
162
|
-
// sort by published
|
|
170
|
+
// sort by published
|
|
163
171
|
.sort((a, b) => {
|
|
164
|
-
return epoch(a
|
|
172
|
+
return epoch(getPublished(a)) - epoch(getPublished(b))
|
|
165
173
|
})
|
|
166
174
|
|
|
167
175
|
return results
|
|
@@ -178,14 +186,24 @@ module.exports = (eleventyConfig, options = {}) => {
|
|
|
178
186
|
|
|
179
187
|
if (eleventyConfig && options) {
|
|
180
188
|
if (!options.domain) {
|
|
181
|
-
throw new Error("domain is a required
|
|
189
|
+
throw new Error("domain is a required field when adding the plugin to your eleventyConfig using addPlugin. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
|
|
182
190
|
}
|
|
183
191
|
|
|
184
|
-
|
|
192
|
+
if (!options.feed) {
|
|
193
|
+
throw new Error("feed is a required field when adding the plugin to your eleventyConfig using addPlugin. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!options.key) {
|
|
197
|
+
throw new Error("key is a required field when adding the plugin to your eleventyConfig using addPlugin. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Liquid Filter
|
|
185
201
|
eleventyConfig.addLiquidFilter("getWebmentions", getWebmentionsFilter)
|
|
202
|
+
|
|
203
|
+
// Nunjucks Filter
|
|
186
204
|
eleventyConfig.addNunjucksAsyncFilter("getWebmentions", getWebmentionsFilter)
|
|
187
205
|
|
|
188
|
-
//
|
|
206
|
+
// Global Data
|
|
189
207
|
eleventyConfig.addGlobalData("webmentions", filteredWebmentions)
|
|
190
208
|
} else {
|
|
191
209
|
// JavaScript
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrisburnell/eleventy-cache-webmentions",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Fetch and cache webmentions using eleventy-fetch.",
|
|
5
5
|
"main": "eleventy-cache-webmentions.js",
|
|
6
6
|
"author": "Chris Burnell <me@chrisburnell.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@11ty/eleventy-fetch": "^3.0.0",
|
|
20
|
-
"dotenv": "^10.0.0",
|
|
21
20
|
"lodash": "^4.17.21",
|
|
22
21
|
"node-fetch": "2.6.5",
|
|
23
22
|
"sanitize-html": "^2.5.2"
|