@chrisburnell/eleventy-cache-webmentions 2.1.6 → 2.1.8
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"68a403136c61abd104ade94e69ba62":"1"},{"cachedAt":
|
|
1
|
+
[{"68a403136c61abd104ade94e69ba62":"1"},{"cachedAt":1723708494710,"type":"2"},"json"]
|
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
const fetch = require("node-fetch");
|
|
2
2
|
const sanitizeHTML = require("sanitize-html");
|
|
3
|
-
const uniqBy = require("lodash
|
|
3
|
+
const uniqBy = require("lodash.uniqby");
|
|
4
4
|
const { AssetCache } = require("@11ty/eleventy-fetch");
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
|
|
7
|
+
const defaults = {
|
|
8
|
+
refresh: false,
|
|
9
|
+
duration: "1d",
|
|
10
|
+
uniqueKey: "webmentions",
|
|
11
|
+
allowedHTML: {
|
|
12
|
+
allowedTags: ["b", "i", "em", "strong", "a"],
|
|
13
|
+
allowedAttributes: {
|
|
14
|
+
a: ["href"],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
allowlist: [],
|
|
18
|
+
blocklist: [],
|
|
19
|
+
urlReplacements: {},
|
|
20
|
+
maximumHtmlLength: 1000,
|
|
21
|
+
maximumHtmlText: "mentioned this in",
|
|
22
|
+
};
|
|
5
23
|
|
|
6
24
|
const absoluteURL = (url, domain) => {
|
|
7
25
|
try {
|
|
8
26
|
return new URL(url, domain).toString();
|
|
9
27
|
} catch (e) {
|
|
10
|
-
console.
|
|
11
|
-
`Trying to convert ${
|
|
28
|
+
console.error(
|
|
29
|
+
`Trying to convert ${chalk.bold(
|
|
30
|
+
url,
|
|
31
|
+
)} to be an absolute url with base ${chalk.bold(
|
|
32
|
+
domain,
|
|
33
|
+
)} and failed.`,
|
|
12
34
|
);
|
|
13
35
|
return url;
|
|
14
36
|
}
|
|
@@ -113,21 +135,42 @@ const getByTypes = (webmentions, allowedTypes) => {
|
|
|
113
135
|
});
|
|
114
136
|
};
|
|
115
137
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
const removeDuplicates = (webmentions) => {
|
|
139
|
+
return uniqBy(webmentions, (webmention) => {
|
|
140
|
+
return getSource(webmention);
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const processBlocklist = (webmentions, blocklist) => {
|
|
145
|
+
return webmentions.filter((webmention) => {
|
|
146
|
+
let url = getSource(webmention);
|
|
147
|
+
let source = getSource(webmention);
|
|
148
|
+
for (let blocklistURL of blocklist) {
|
|
149
|
+
if (
|
|
150
|
+
url.includes(blocklistURL.replace(/\/?$/, "/")) ||
|
|
151
|
+
source.includes(blocklistURL.replace(/\/?$/, "/"))
|
|
152
|
+
) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const processAllowlist = (webmentions, allowlist) => {
|
|
161
|
+
return webmentions.filter((webmention) => {
|
|
162
|
+
let url = getSource(webmention);
|
|
163
|
+
let source = getSource(webmention);
|
|
164
|
+
for (let allowlistURL of allowlist) {
|
|
165
|
+
if (
|
|
166
|
+
url.includes(allowlistURL.replace(/\/?$/, "/")) ||
|
|
167
|
+
source.includes(allowlistURL.replace(/\/?$/, "/"))
|
|
168
|
+
) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
});
|
|
131
174
|
};
|
|
132
175
|
|
|
133
176
|
const performFetch = async (options, webmentions, url) => {
|
|
@@ -141,10 +184,10 @@ const performFetch = async (options, webmentions, url) => {
|
|
|
141
184
|
|
|
142
185
|
if (!options.key in feed) {
|
|
143
186
|
console.log(
|
|
144
|
-
`[${hostname(options.domain)}] ${
|
|
187
|
+
`${chalk.grey(`[${hostname(options.domain)}]`)} ${
|
|
145
188
|
options.key
|
|
146
|
-
} was not found as a key in the response from ${
|
|
147
|
-
options.feed,
|
|
189
|
+
} was not found as a key in the response from ${chalkf.bold(
|
|
190
|
+
hostname(options.feed),
|
|
148
191
|
)}!`,
|
|
149
192
|
);
|
|
150
193
|
return Promise.reject(response);
|
|
@@ -153,43 +196,14 @@ const performFetch = async (options, webmentions, url) => {
|
|
|
153
196
|
// Combine newly-fetched Webmentions with cached Webmentions
|
|
154
197
|
webmentions = feed[options.key].concat(webmentions);
|
|
155
198
|
// Remove duplicates by source URL
|
|
156
|
-
webmentions =
|
|
157
|
-
[...feed[options.key], ...webmentions],
|
|
158
|
-
(webmention) => {
|
|
159
|
-
return getSource(webmention);
|
|
160
|
-
},
|
|
161
|
-
);
|
|
199
|
+
webmentions = removeDuplicates(webmentions);
|
|
162
200
|
// Process the blocklist, if it has any entries
|
|
163
201
|
if (options.blocklist.length) {
|
|
164
|
-
webmentions = webmentions.
|
|
165
|
-
let url = getSource(webmention);
|
|
166
|
-
let source = getSource(webmention);
|
|
167
|
-
for (let blocklistURL of options.blocklist) {
|
|
168
|
-
if (
|
|
169
|
-
url.includes(blocklistURL.replace(/\/?$/, "/")) ||
|
|
170
|
-
source.includes(blocklistURL.replace(/\/?$/, "/"))
|
|
171
|
-
) {
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return true;
|
|
176
|
-
});
|
|
202
|
+
webmentions = processBlocklist(webmentions, options.blocklist);
|
|
177
203
|
}
|
|
178
204
|
// Process the allowlist, if it has any entries
|
|
179
205
|
if (options.allowlist.length) {
|
|
180
|
-
webmentions = webmentions.
|
|
181
|
-
let url = getSource(webmention);
|
|
182
|
-
let source = getSource(webmention);
|
|
183
|
-
for (let allowlistURL of options.allowlist) {
|
|
184
|
-
if (
|
|
185
|
-
url.includes(allowlistURL.replace(/\/?$/, "/")) ||
|
|
186
|
-
source.includes(allowlistURL.replace(/\/?$/, "/"))
|
|
187
|
-
) {
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return false;
|
|
192
|
-
});
|
|
206
|
+
webmentions = processAllowlist(webmentions, options.allowlist);
|
|
193
207
|
}
|
|
194
208
|
// Sort webmentions by received date for getting most recent Webmention on subsequent requests
|
|
195
209
|
webmentions = webmentions.sort((a, b) => {
|
|
@@ -203,10 +217,10 @@ const performFetch = async (options, webmentions, url) => {
|
|
|
203
217
|
})
|
|
204
218
|
.catch((error) => {
|
|
205
219
|
console.log(
|
|
206
|
-
|
|
207
|
-
options.domain
|
|
208
|
-
)}
|
|
209
|
-
options.feed,
|
|
220
|
+
`${chalk.grey(
|
|
221
|
+
`[${hostname(options.domain)}]`,
|
|
222
|
+
)} Something went wrong with your request to ${chalk.bold(
|
|
223
|
+
hostname(options.feed),
|
|
210
224
|
)}!`,
|
|
211
225
|
error,
|
|
212
226
|
);
|
|
@@ -232,7 +246,10 @@ const fetchWebmentions = async (options) => {
|
|
|
232
246
|
);
|
|
233
247
|
}
|
|
234
248
|
|
|
235
|
-
let asset = new AssetCache(
|
|
249
|
+
let asset = new AssetCache(
|
|
250
|
+
options.uniqueKey || `webmentions-${hostname(options.domain)}`,
|
|
251
|
+
options.directory,
|
|
252
|
+
);
|
|
236
253
|
asset.ensureDir();
|
|
237
254
|
|
|
238
255
|
let webmentions = [];
|
|
@@ -250,6 +267,7 @@ const fetchWebmentions = async (options) => {
|
|
|
250
267
|
// If there is a cached file but it is outside of expiry, fetch fresh
|
|
251
268
|
// results since the most recent Webmention
|
|
252
269
|
if (!asset.isCacheValid(options.refresh ? "0s" : options.duration)) {
|
|
270
|
+
const performanceStart = process.hrtime();
|
|
253
271
|
// Get the received date of the most recent Webmention, if it exists
|
|
254
272
|
const since = webmentions.length ? getReceived(webmentions[0]) : false;
|
|
255
273
|
// Build the URL for the fetch request
|
|
@@ -305,14 +323,29 @@ const fetchWebmentions = async (options) => {
|
|
|
305
323
|
webmentions = fetched.filtered;
|
|
306
324
|
}
|
|
307
325
|
|
|
326
|
+
// Process the blocklist, if it has any entries
|
|
327
|
+
if (options.blocklist.length) {
|
|
328
|
+
webmentions = processBlocklist(webmentions, options.blocklist);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Process the allowlist, if it has any entries
|
|
332
|
+
if (options.allowlist.length) {
|
|
333
|
+
webmentions = processAllowlist(webmentions, options.allowlist);
|
|
334
|
+
}
|
|
335
|
+
|
|
308
336
|
await asset.save(webmentions, "json");
|
|
309
337
|
|
|
338
|
+
const performance = process.hrtime(performanceStart);
|
|
339
|
+
|
|
310
340
|
// Add a console message with the number of fetched and processed Webmentions, if any
|
|
311
341
|
if (webmentionsCachedLength < webmentions.length) {
|
|
312
342
|
console.log(
|
|
313
|
-
`[${hostname(options.domain)}] ${
|
|
314
|
-
webmentions.length - webmentionsCachedLength
|
|
315
|
-
} new Webmentions fetched into cache
|
|
343
|
+
`${chalk.grey(`[${hostname(options.domain)}]`)} ${chalk.bold(
|
|
344
|
+
webmentions.length - webmentionsCachedLength,
|
|
345
|
+
)} new Webmentions fetched into cache in ${chalk.bold(
|
|
346
|
+
(performance[0] + performance[1] / 1e9).toFixed(3) +
|
|
347
|
+
" seconds",
|
|
348
|
+
)}.`,
|
|
316
349
|
);
|
|
317
350
|
}
|
|
318
351
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrisburnell/eleventy-cache-webmentions",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8",
|
|
4
4
|
"description": "Cache webmentions using eleventy-fetch and make them available to use in collections, layouts, pages, etc. in Eleventy.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
],
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@11ty/eleventy-fetch": "^4.0.1",
|
|
55
|
-
"
|
|
55
|
+
"chalk": "^4.1.2",
|
|
56
|
+
"lodash.uniqby": "^4.7.0",
|
|
56
57
|
"node-fetch": "2.6.7",
|
|
57
58
|
"sanitize-html": "^2.13.0"
|
|
58
59
|
},
|