@chrisburnell/eleventy-cache-webmentions 2.1.2 → 2.1.3-beta.3
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/README.md +9 -17
- package/eleventy-cache-webmentions.js +283 -185
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,6 +82,12 @@ Make sure you get the correct values for this configuration. Check below for bot
|
|
|
82
82
|
<td>See <a href="https://www.11ty.dev/docs/plugins/cache/#cache-directory">Eleventy Fetch’s Cache Directory</a> for more information.</td>
|
|
83
83
|
<td>1.1.2</td>
|
|
84
84
|
</tr>
|
|
85
|
+
<tr>
|
|
86
|
+
<td><code>refresh</code></td>
|
|
87
|
+
<td><code>false</code></td>
|
|
88
|
+
<td>Forces fresh results from the Webmention endpoint every time.</td>
|
|
89
|
+
<td>2.1.3</td>
|
|
90
|
+
</tr>
|
|
85
91
|
<tr>
|
|
86
92
|
<td><code>duration</code></td>
|
|
87
93
|
<td><code>"1d"</code> <em>or</em> 1 day</td>
|
|
@@ -205,9 +211,6 @@ webmentions.forEach((webmention) => {
|
|
|
205
211
|
<summary>Liquid / Nunjucks</summary>
|
|
206
212
|
|
|
207
213
|
```twig
|
|
208
|
-
{# get Array of Webmentions for a given URL #}
|
|
209
|
-
{% set webmentions = ("https://example.com" + page.url) | getWebmentions %}
|
|
210
|
-
|
|
211
214
|
{# filter Webmentions by their response type #}
|
|
212
215
|
{{ set responses = webmentions | getWebmentionsByTypes(['mention-of', 'in-reply-to']) }}
|
|
213
216
|
|
|
@@ -227,7 +230,7 @@ webmentions.forEach((webmention) => {
|
|
|
227
230
|
|
|
228
231
|
</details>
|
|
229
232
|
|
|
230
|
-
|
|
233
|
+
### Attach Webmentions to Pages using Directory Data
|
|
231
234
|
|
|
232
235
|
Using [Eleventy’s Data Cascade](https://www.11ty.dev/docs/data-cascade/), you can attach Webmentions to each page by using [Directory Specific Data Files](https://www.11ty.dev/docs/data-template-dir/).
|
|
233
236
|
|
|
@@ -281,18 +284,7 @@ module.exports = (eleventyConfig) => {
|
|
|
281
284
|
}
|
|
282
285
|
```
|
|
283
286
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
If you would rather get Webmentions for a given page directly from a Layout/Include/Page itself, you can do so using the Filter, `getWebmentions`:
|
|
287
|
-
|
|
288
|
-
```twig
|
|
289
|
-
{% set webmentions = ("https://example.com" + page.url) | getWebmentions %}
|
|
290
|
-
{% for webmention in webmentions %}
|
|
291
|
-
...
|
|
292
|
-
{% endfor %}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## Get specific types of Webmentions
|
|
287
|
+
### Get specific types of Webmentions
|
|
296
288
|
|
|
297
289
|
Instead of getting all the Webmentions for a given page, you may want to grab only certain types of Webmentions. This is useful if you want to display different types of Webmentions separately, e.g.:
|
|
298
290
|
|
|
@@ -304,7 +296,7 @@ Instead of getting all the Webmentions for a given page, you may want to grab on
|
|
|
304
296
|
{% set replies = webmentions | getWebmentionsByTypes(['mention-of', 'in-reply-to']) %}
|
|
305
297
|
```
|
|
306
298
|
|
|
307
|
-
|
|
299
|
+
### Get all Webmentions at once
|
|
308
300
|
|
|
309
301
|
If you need it, the plugin also makes available an Object containing your cached Webmentions organised in key:value pairs, where each key is a full URL on your website and its value is an Array of Webmentions sent to that URL:
|
|
310
302
|
|
|
@@ -1,73 +1,111 @@
|
|
|
1
|
-
const fetch = require("node-fetch")
|
|
2
|
-
const sanitizeHTML = require("sanitize-html")
|
|
3
|
-
const uniqBy = require("lodash/uniqBy")
|
|
4
|
-
const { AssetCache } = require("@11ty/eleventy-fetch")
|
|
1
|
+
const fetch = require("node-fetch");
|
|
2
|
+
const sanitizeHTML = require("sanitize-html");
|
|
3
|
+
const uniqBy = require("lodash/uniqBy");
|
|
4
|
+
const { AssetCache } = require("@11ty/eleventy-fetch");
|
|
5
5
|
|
|
6
6
|
const absoluteURL = (url, domain) => {
|
|
7
7
|
try {
|
|
8
|
-
return new URL(url, domain).toString()
|
|
8
|
+
return new URL(url, domain).toString();
|
|
9
9
|
} catch (e) {
|
|
10
|
-
console.log(
|
|
11
|
-
|
|
10
|
+
console.log(
|
|
11
|
+
`Trying to convert ${url} to be an absolute url with base ${domain} and failed.`,
|
|
12
|
+
);
|
|
13
|
+
return url;
|
|
12
14
|
}
|
|
13
|
-
}
|
|
15
|
+
};
|
|
14
16
|
|
|
15
17
|
const baseUrl = (url) => {
|
|
16
|
-
let hashSplit = url.split("#")
|
|
17
|
-
let queryparamSplit = hashSplit[0].split("?")
|
|
18
|
-
return queryparamSplit[0]
|
|
19
|
-
}
|
|
18
|
+
let hashSplit = url.split("#");
|
|
19
|
+
let queryparamSplit = hashSplit[0].split("?");
|
|
20
|
+
return queryparamSplit[0];
|
|
21
|
+
};
|
|
20
22
|
|
|
21
23
|
const fixUrl = (url, urlReplacements) => {
|
|
22
|
-
return Object.entries(urlReplacements).reduce(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
24
|
+
return Object.entries(urlReplacements).reduce(
|
|
25
|
+
(accumulator, [key, value]) => {
|
|
26
|
+
const regex = new RegExp(key, "g");
|
|
27
|
+
return accumulator.replace(regex, value);
|
|
28
|
+
},
|
|
29
|
+
url,
|
|
30
|
+
);
|
|
31
|
+
};
|
|
27
32
|
|
|
28
33
|
const hostname = (value) => {
|
|
29
34
|
if (typeof value === "string" && value.includes("//")) {
|
|
30
|
-
const urlObject = new URL(value)
|
|
31
|
-
return urlObject.hostname
|
|
35
|
+
const urlObject = new URL(value);
|
|
36
|
+
return urlObject.hostname;
|
|
32
37
|
}
|
|
33
|
-
return value
|
|
34
|
-
}
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
35
40
|
|
|
36
41
|
const epoch = (value) => {
|
|
37
|
-
return new Date(value).getTime()
|
|
38
|
-
}
|
|
42
|
+
return new Date(value).getTime();
|
|
43
|
+
};
|
|
39
44
|
|
|
40
45
|
const getPublished = (webmention) => {
|
|
41
|
-
return
|
|
42
|
-
|
|
46
|
+
return (
|
|
47
|
+
webmention?.["data"]?.["published"] ||
|
|
48
|
+
webmention["published"] ||
|
|
49
|
+
webmention["wm-received"] ||
|
|
50
|
+
webmention["verified_date"]
|
|
51
|
+
);
|
|
52
|
+
};
|
|
43
53
|
|
|
44
54
|
const getReceived = (webmention) => {
|
|
45
|
-
return
|
|
46
|
-
|
|
55
|
+
return (
|
|
56
|
+
webmention["wm-received"] ||
|
|
57
|
+
webmention["verified_date"] ||
|
|
58
|
+
webmention?.["data"]?.["published"] ||
|
|
59
|
+
webmention["published"]
|
|
60
|
+
);
|
|
61
|
+
};
|
|
47
62
|
|
|
48
63
|
const getContent = (webmention) => {
|
|
49
|
-
return
|
|
50
|
-
|
|
64
|
+
return (
|
|
65
|
+
webmention?.["contentSanitized"] ||
|
|
66
|
+
webmention?.["content"]?.["html"] ||
|
|
67
|
+
webmention?.["content"]?.["value"] ||
|
|
68
|
+
webmention?.["content"] ||
|
|
69
|
+
webmention?.["data"]?.["content"] ||
|
|
70
|
+
""
|
|
71
|
+
);
|
|
72
|
+
};
|
|
51
73
|
|
|
52
74
|
const getSource = (webmention) => {
|
|
53
|
-
return
|
|
54
|
-
|
|
75
|
+
return (
|
|
76
|
+
webmention?.["data"]?.["url"] ||
|
|
77
|
+
webmention["url"] ||
|
|
78
|
+
webmention["wm-source"] ||
|
|
79
|
+
webmention["source"]
|
|
80
|
+
);
|
|
81
|
+
};
|
|
55
82
|
|
|
56
83
|
const getTarget = (webmention) => {
|
|
57
|
-
return webmention["wm-target"] || webmention["target"]
|
|
58
|
-
}
|
|
84
|
+
return webmention["wm-target"] || webmention["target"];
|
|
85
|
+
};
|
|
59
86
|
|
|
60
87
|
const getType = (webmention) => {
|
|
61
|
-
return
|
|
62
|
-
|
|
88
|
+
return (
|
|
89
|
+
webmention["wm-property"] ||
|
|
90
|
+
webmention?.["activity"]?.["type"] ||
|
|
91
|
+
webmention["type"]
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const getByType = (webmentions, allowedType) => {
|
|
96
|
+
return webmentions.filter((webmention) => {
|
|
97
|
+
return allowedTypes === getType(webmention);
|
|
98
|
+
});
|
|
99
|
+
};
|
|
63
100
|
|
|
64
101
|
const getByTypes = (webmentions, allowedTypes) => {
|
|
65
102
|
return webmentions.filter((webmention) => {
|
|
66
|
-
return allowedTypes.includes(getType(webmention))
|
|
67
|
-
})
|
|
68
|
-
}
|
|
103
|
+
return allowedTypes.includes(getType(webmention));
|
|
104
|
+
});
|
|
105
|
+
};
|
|
69
106
|
|
|
70
107
|
const defaults = {
|
|
108
|
+
refresh: false,
|
|
71
109
|
duration: "1d",
|
|
72
110
|
uniqueKey: "webmentions",
|
|
73
111
|
allowedHTML: {
|
|
@@ -81,259 +119,319 @@ const defaults = {
|
|
|
81
119
|
urlReplacements: {},
|
|
82
120
|
maximumHtmlLength: 1000,
|
|
83
121
|
maximumHtmlText: "mentioned this in",
|
|
84
|
-
}
|
|
122
|
+
};
|
|
85
123
|
|
|
86
124
|
const performFetch = async (options, webmentions, url) => {
|
|
87
125
|
return await fetch(url)
|
|
88
126
|
.then(async (response) => {
|
|
89
|
-
if (response.ok) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
return Promise.reject(response);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const feed = await response.json();
|
|
132
|
+
|
|
133
|
+
if (!options.key in feed) {
|
|
134
|
+
console.log(
|
|
135
|
+
`[${hostname(options.domain)}] ${
|
|
136
|
+
options.key
|
|
137
|
+
} was not found as a key in the response from ${hostname(
|
|
138
|
+
options.feed,
|
|
139
|
+
)}!`,
|
|
140
|
+
);
|
|
141
|
+
return Promise.reject(response);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Combine newly-fetched Webmentions with cached Webmentions
|
|
145
|
+
webmentions = feed[options.key].concat(webmentions);
|
|
146
|
+
// Remove duplicates by source URL
|
|
147
|
+
webmentions = uniqBy(
|
|
148
|
+
[...feed[options.key], ...webmentions],
|
|
149
|
+
(webmention) => {
|
|
150
|
+
return getSource(webmention);
|
|
151
|
+
},
|
|
152
|
+
);
|
|
153
|
+
// Process the blocklist, if it has any entries
|
|
154
|
+
if (options.blocklist.length) {
|
|
155
|
+
webmentions = webmentions.filter((webmention) => {
|
|
156
|
+
let sourceUrl = getSource(webmention);
|
|
157
|
+
for (let url of options.blocklist) {
|
|
158
|
+
if (sourceUrl.includes(url.replace(/\/?$/, "/"))) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
109
161
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
return
|
|
120
|
-
}
|
|
162
|
+
return true;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Process the allowlist, if it has any entries
|
|
166
|
+
if (options.allowlist.length) {
|
|
167
|
+
webmentions = webmentions.filter((webmention) => {
|
|
168
|
+
let sourceUrl = getSource(webmention);
|
|
169
|
+
for (let url of options.allowlist) {
|
|
170
|
+
if (sourceUrl.includes(url.replace(/\/?$/, "/"))) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
121
173
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return epoch(getReceived(b)) - epoch(getReceived(a))
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
found: feed[options.key].length,
|
|
129
|
-
filtered: webmentions,
|
|
130
|
-
}
|
|
174
|
+
return false;
|
|
175
|
+
});
|
|
131
176
|
}
|
|
132
|
-
|
|
177
|
+
// Sort webmentions by received date for getting most recent Webmention on subsequent requests
|
|
178
|
+
webmentions = webmentions.sort((a, b) => {
|
|
179
|
+
return epoch(getReceived(b)) - epoch(getReceived(a));
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
found: feed[options.key].length,
|
|
184
|
+
filtered: webmentions,
|
|
185
|
+
};
|
|
133
186
|
})
|
|
134
187
|
.catch((error) => {
|
|
135
|
-
console.log(
|
|
136
|
-
|
|
137
|
-
|
|
188
|
+
console.log(
|
|
189
|
+
`[${hostname(
|
|
190
|
+
options.domain,
|
|
191
|
+
)}] Something went wrong with your request to ${hostname(
|
|
192
|
+
options.feed,
|
|
193
|
+
)}!`,
|
|
194
|
+
error,
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
};
|
|
138
198
|
|
|
139
199
|
const fetchWebmentions = async (options) => {
|
|
140
200
|
if (!options.domain) {
|
|
141
|
-
throw new Error(
|
|
201
|
+
throw new Error(
|
|
202
|
+
"`domain` is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.",
|
|
203
|
+
);
|
|
142
204
|
}
|
|
143
205
|
|
|
144
206
|
if (!options.feed) {
|
|
145
|
-
throw new Error(
|
|
207
|
+
throw new Error(
|
|
208
|
+
"`feed` is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.",
|
|
209
|
+
);
|
|
146
210
|
}
|
|
147
211
|
|
|
148
212
|
if (!options.key) {
|
|
149
|
-
throw new Error(
|
|
213
|
+
throw new Error(
|
|
214
|
+
"`key` is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.",
|
|
215
|
+
);
|
|
150
216
|
}
|
|
151
217
|
|
|
152
|
-
let asset = new AssetCache(options.uniqueKey, options.directory)
|
|
153
|
-
asset.ensureDir()
|
|
218
|
+
let asset = new AssetCache(options.uniqueKey, options.directory);
|
|
219
|
+
asset.ensureDir();
|
|
154
220
|
|
|
155
|
-
let webmentions = []
|
|
221
|
+
let webmentions = [];
|
|
156
222
|
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
223
|
+
// Unless specifically getting fresh Webmentions, if there is a cached file
|
|
224
|
+
// at all, grab its contents now
|
|
225
|
+
if (asset.isCacheValid("9001y") && !options.refresh) {
|
|
226
|
+
webmentions = await asset.getCachedValue();
|
|
160
227
|
}
|
|
161
228
|
|
|
162
229
|
// Get the number of cached Webmentions for diffing against fetched
|
|
163
230
|
// Webmentions later
|
|
164
|
-
const webmentionsCachedLength = webmentions.length
|
|
231
|
+
const webmentionsCachedLength = webmentions.length;
|
|
165
232
|
|
|
166
233
|
// If there is a cached file but it is outside of expiry, fetch fresh
|
|
167
234
|
// results since the most recent Webmention
|
|
168
|
-
if (!asset.isCacheValid(options.duration)) {
|
|
235
|
+
if (!asset.isCacheValid(options.refresh ? "0s" : options.duration)) {
|
|
169
236
|
// Get the received date of the most recent Webmention, if it exists
|
|
170
|
-
const since = webmentions.length ? getReceived(webmentions[0]) : false
|
|
237
|
+
const since = webmentions.length ? getReceived(webmentions[0]) : false;
|
|
171
238
|
// Build the URL for the fetch request
|
|
172
|
-
const url = `${options.feed}${
|
|
239
|
+
const url = `${options.feed}${
|
|
240
|
+
since
|
|
241
|
+
? `${options.feed.includes("?") ? "&" : "?"}since=${since}`
|
|
242
|
+
: ""
|
|
243
|
+
}`;
|
|
173
244
|
|
|
174
245
|
// If using webmention.io, loop through pages until no results found
|
|
175
246
|
if (url.includes("https://webmention.io")) {
|
|
247
|
+
const urlObject = new URL(url);
|
|
248
|
+
const perPage =
|
|
249
|
+
Number(urlObject.searchParams.get("per-page")) || 1000;
|
|
250
|
+
urlObject.searchParams.delete("per-page");
|
|
176
251
|
// Start on page 0, to increment per subsequent request
|
|
177
|
-
let page = 0
|
|
252
|
+
let page = 0;
|
|
178
253
|
// Loop until a break condition is hit
|
|
179
254
|
while (true) {
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
const fetched = await performFetch(
|
|
255
|
+
const urlPaginated =
|
|
256
|
+
urlObject.href + `&per-page=${perPage}&page=${page}`;
|
|
257
|
+
const fetched = await performFetch(
|
|
258
|
+
options,
|
|
259
|
+
webmentions,
|
|
260
|
+
urlPaginated,
|
|
261
|
+
);
|
|
183
262
|
|
|
184
263
|
// An error occurred during fetching paged results → break
|
|
185
264
|
if (!fetched && !fetched.found && !fetched.filtered) {
|
|
186
|
-
break
|
|
265
|
+
break;
|
|
187
266
|
}
|
|
188
267
|
|
|
189
268
|
// Page has no Webmentions → break
|
|
190
269
|
if (fetched.found === 0) {
|
|
191
|
-
break
|
|
270
|
+
break;
|
|
192
271
|
}
|
|
193
272
|
|
|
194
|
-
webmentions = fetched.filtered
|
|
273
|
+
webmentions = fetched.filtered;
|
|
195
274
|
|
|
196
275
|
// If there are less Webmentions found than should be in each
|
|
197
276
|
// page → break
|
|
198
277
|
if (fetched.found < perPage) {
|
|
199
|
-
break
|
|
278
|
+
break;
|
|
200
279
|
}
|
|
201
280
|
|
|
202
281
|
// Increment page
|
|
203
|
-
page += 1
|
|
282
|
+
page += 1;
|
|
204
283
|
// Throttle next request
|
|
205
|
-
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
284
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
206
285
|
}
|
|
207
286
|
} else {
|
|
208
|
-
const fetched = await performFetch(options, webmentions, url)
|
|
209
|
-
webmentions = fetched.filtered
|
|
287
|
+
const fetched = await performFetch(options, webmentions, url);
|
|
288
|
+
webmentions = fetched.filtered;
|
|
210
289
|
}
|
|
211
290
|
|
|
212
|
-
await asset.save(webmentions, "json")
|
|
291
|
+
await asset.save(webmentions, "json");
|
|
213
292
|
|
|
214
293
|
// Add a console message with the number of fetched and processed Webmentions, if any
|
|
215
294
|
if (webmentionsCachedLength < webmentions.length) {
|
|
216
|
-
console.log(
|
|
295
|
+
console.log(
|
|
296
|
+
`[${hostname(options.domain)}] ${
|
|
297
|
+
webmentions.length - webmentionsCachedLength
|
|
298
|
+
} new Webmentions fetched into cache.`,
|
|
299
|
+
);
|
|
217
300
|
}
|
|
218
301
|
}
|
|
219
302
|
|
|
220
|
-
return webmentions
|
|
221
|
-
}
|
|
303
|
+
return webmentions;
|
|
304
|
+
};
|
|
222
305
|
|
|
223
|
-
let filtered = {}
|
|
306
|
+
let filtered = {};
|
|
224
307
|
const filteredWebmentions = async (options) => {
|
|
225
308
|
if (Object.entries(filtered).length) {
|
|
226
|
-
return filtered
|
|
309
|
+
return filtered;
|
|
227
310
|
}
|
|
228
311
|
|
|
229
|
-
let rawWebmentions = await fetchWebmentions(options)
|
|
312
|
+
let rawWebmentions = await fetchWebmentions(options);
|
|
230
313
|
|
|
231
314
|
// Fix local URLs based on urlReplacements and sort Webmentions into groups
|
|
232
315
|
// by target base URL
|
|
233
316
|
rawWebmentions.forEach((webmention) => {
|
|
234
|
-
let url = baseUrl(
|
|
317
|
+
let url = baseUrl(
|
|
318
|
+
fixUrl(
|
|
319
|
+
getTarget(webmention).replace(/\/?$/, "/"),
|
|
320
|
+
options.urlReplacements,
|
|
321
|
+
),
|
|
322
|
+
);
|
|
235
323
|
|
|
236
324
|
if (!filtered[url]) {
|
|
237
|
-
filtered[url] = []
|
|
325
|
+
filtered[url] = [];
|
|
238
326
|
}
|
|
239
327
|
|
|
240
|
-
filtered[url].push(webmention)
|
|
241
|
-
})
|
|
328
|
+
filtered[url].push(webmention);
|
|
329
|
+
});
|
|
242
330
|
|
|
243
|
-
return filtered
|
|
244
|
-
}
|
|
331
|
+
return filtered;
|
|
332
|
+
};
|
|
245
333
|
|
|
246
334
|
const getWebmentions = async (options, url, allowedTypes = {}) => {
|
|
247
|
-
const webmentions = await filteredWebmentions(options)
|
|
248
|
-
url = absoluteURL(url, options.domain)
|
|
335
|
+
const webmentions = await filteredWebmentions(options);
|
|
336
|
+
url = absoluteURL(url, options.domain);
|
|
249
337
|
|
|
250
338
|
if (!url || !webmentions || !webmentions[url]) {
|
|
251
|
-
return []
|
|
339
|
+
return [];
|
|
252
340
|
}
|
|
253
341
|
|
|
254
342
|
return (
|
|
255
343
|
webmentions[url]
|
|
256
344
|
// Filter webmentions by allowed response post types
|
|
257
345
|
.filter((entry) => {
|
|
258
|
-
return typeof allowedTypes === "object" &&
|
|
346
|
+
return typeof allowedTypes === "object" &&
|
|
347
|
+
Object.keys(allowedTypes).length
|
|
348
|
+
? allowedTypes.includes(getType(entry))
|
|
349
|
+
: true;
|
|
259
350
|
})
|
|
260
351
|
// Sanitize content of webmentions against HTML limit
|
|
261
352
|
.map((entry) => {
|
|
262
|
-
const html = getContent(entry)
|
|
353
|
+
const html = getContent(entry);
|
|
263
354
|
|
|
264
355
|
if (html.length) {
|
|
265
|
-
entry.contentSanitized = sanitizeHTML(
|
|
356
|
+
entry.contentSanitized = sanitizeHTML(
|
|
357
|
+
html,
|
|
358
|
+
options.allowedHTML,
|
|
359
|
+
);
|
|
266
360
|
if (html.length > options.maximumHtmlLength) {
|
|
267
|
-
entry.contentSanitized = `${
|
|
361
|
+
entry.contentSanitized = `${
|
|
362
|
+
options.maximumHtmlText
|
|
363
|
+
} <a href="${getSource(entry)}">${getSource(
|
|
364
|
+
entry,
|
|
365
|
+
)}</a>`;
|
|
268
366
|
}
|
|
269
367
|
}
|
|
270
368
|
|
|
271
|
-
return entry
|
|
369
|
+
return entry;
|
|
272
370
|
})
|
|
273
371
|
// Sort by published
|
|
274
372
|
.sort((a, b) => {
|
|
275
|
-
return epoch(getPublished(a)) - epoch(getPublished(b))
|
|
373
|
+
return epoch(getPublished(a)) - epoch(getPublished(b));
|
|
276
374
|
})
|
|
277
|
-
)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const getWebmentionsFilter = async (options, url, allowedTypes, callback) => {
|
|
281
|
-
if (typeof callback !== "function") {
|
|
282
|
-
callback = allowedTypes
|
|
283
|
-
allowedTypes = {}
|
|
284
|
-
}
|
|
285
|
-
const webmentions = await getWebmentions(options, url, allowedTypes)
|
|
286
|
-
callback(null, webmentions)
|
|
287
|
-
}
|
|
375
|
+
);
|
|
376
|
+
};
|
|
288
377
|
|
|
289
378
|
const eleventyCacheWebmentions = (eleventyConfig, options = {}) => {
|
|
290
|
-
options = Object.assign(defaults, options)
|
|
379
|
+
options = Object.assign(defaults, options);
|
|
291
380
|
|
|
292
381
|
// Global Data
|
|
293
|
-
eleventyConfig.addGlobalData("webmentionsDefaults", defaults)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
382
|
+
eleventyConfig.addGlobalData("webmentionsDefaults", defaults);
|
|
383
|
+
eleventyConfig.addGlobalData("webmentionsOptions", options);
|
|
384
|
+
const filtered = async () => await filteredWebmentions(options);
|
|
385
|
+
eleventyConfig.addGlobalData("webmentionsByUrl", filtered);
|
|
386
|
+
const unfiltered = async () =>
|
|
387
|
+
await filteredWebmentions(options).then((filtered) =>
|
|
388
|
+
Object.values(filtered).reduce(
|
|
389
|
+
(array, webmentions) => [...array, ...webmentions],
|
|
390
|
+
[],
|
|
391
|
+
),
|
|
392
|
+
);
|
|
393
|
+
eleventyConfig.addGlobalData("webmentionsAll", unfiltered);
|
|
298
394
|
|
|
299
395
|
// Liquid Filters
|
|
300
|
-
eleventyConfig.addLiquidFilter("
|
|
301
|
-
eleventyConfig.addLiquidFilter("getWebmentionsByTypes", getByTypes)
|
|
302
|
-
eleventyConfig.addLiquidFilter("getWebmentionPublished", getPublished)
|
|
303
|
-
eleventyConfig.addLiquidFilter("getWebmentionReceived", getReceived)
|
|
304
|
-
eleventyConfig.addLiquidFilter("getWebmentionContent", getContent)
|
|
305
|
-
eleventyConfig.addLiquidFilter("getWebmentionSource", getSource)
|
|
306
|
-
eleventyConfig.addLiquidFilter("getWebmentionTarget", getTarget)
|
|
307
|
-
eleventyConfig.addLiquidFilter("getWebmentionType", getType)
|
|
396
|
+
eleventyConfig.addLiquidFilter("getWebmentionsByType", getByType);
|
|
397
|
+
eleventyConfig.addLiquidFilter("getWebmentionsByTypes", getByTypes);
|
|
398
|
+
eleventyConfig.addLiquidFilter("getWebmentionPublished", getPublished);
|
|
399
|
+
eleventyConfig.addLiquidFilter("getWebmentionReceived", getReceived);
|
|
400
|
+
eleventyConfig.addLiquidFilter("getWebmentionContent", getContent);
|
|
401
|
+
eleventyConfig.addLiquidFilter("getWebmentionSource", getSource);
|
|
402
|
+
eleventyConfig.addLiquidFilter("getWebmentionTarget", getTarget);
|
|
403
|
+
eleventyConfig.addLiquidFilter("getWebmentionType", getType);
|
|
308
404
|
|
|
309
405
|
// Nunjucks Filters
|
|
310
|
-
eleventyConfig.
|
|
311
|
-
eleventyConfig.addNunjucksFilter("getWebmentionsByTypes", getByTypes)
|
|
312
|
-
eleventyConfig.addNunjucksFilter("getWebmentionPublished", getPublished)
|
|
313
|
-
eleventyConfig.addNunjucksFilter("getWebmentionReceived", getReceived)
|
|
314
|
-
eleventyConfig.addNunjucksFilter("getWebmentionContent", getContent)
|
|
315
|
-
eleventyConfig.addNunjucksFilter("getWebmentionSource", getSource)
|
|
316
|
-
eleventyConfig.addNunjucksFilter("getWebmentionTarget", getTarget)
|
|
317
|
-
eleventyConfig.addNunjucksFilter("getWebmentionType", getType)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
module.exports = eleventyCacheWebmentions
|
|
321
|
-
module.exports.defaults = defaults
|
|
322
|
-
module.exports.filteredWebmentions = filteredWebmentions
|
|
323
|
-
module.exports.webmentionsByUrl = filteredWebmentions
|
|
324
|
-
module.exports.fetchWebmentions = fetchWebmentions
|
|
325
|
-
module.exports.getWebmentions = getWebmentions
|
|
326
|
-
module.exports.
|
|
327
|
-
module.exports.
|
|
328
|
-
module.exports.
|
|
329
|
-
module.exports.
|
|
330
|
-
module.exports.
|
|
331
|
-
module.exports.
|
|
332
|
-
module.exports.
|
|
333
|
-
module.exports.
|
|
334
|
-
module.exports.
|
|
335
|
-
module.exports.
|
|
336
|
-
module.exports.
|
|
337
|
-
module.exports.
|
|
338
|
-
module.exports.
|
|
339
|
-
module.exports.
|
|
406
|
+
eleventyConfig.addNunjucksFilter("getWebmentionsByType", getByType);
|
|
407
|
+
eleventyConfig.addNunjucksFilter("getWebmentionsByTypes", getByTypes);
|
|
408
|
+
eleventyConfig.addNunjucksFilter("getWebmentionPublished", getPublished);
|
|
409
|
+
eleventyConfig.addNunjucksFilter("getWebmentionReceived", getReceived);
|
|
410
|
+
eleventyConfig.addNunjucksFilter("getWebmentionContent", getContent);
|
|
411
|
+
eleventyConfig.addNunjucksFilter("getWebmentionSource", getSource);
|
|
412
|
+
eleventyConfig.addNunjucksFilter("getWebmentionTarget", getTarget);
|
|
413
|
+
eleventyConfig.addNunjucksFilter("getWebmentionType", getType);
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
module.exports = eleventyCacheWebmentions;
|
|
417
|
+
module.exports.defaults = defaults;
|
|
418
|
+
module.exports.filteredWebmentions = filteredWebmentions;
|
|
419
|
+
module.exports.webmentionsByUrl = filteredWebmentions;
|
|
420
|
+
module.exports.fetchWebmentions = fetchWebmentions;
|
|
421
|
+
module.exports.getWebmentions = getWebmentions;
|
|
422
|
+
module.exports.getByType = getByType;
|
|
423
|
+
module.exports.getWebmentionsByType = getByType;
|
|
424
|
+
module.exports.getByTypes = getByTypes;
|
|
425
|
+
module.exports.getWebmentionsByTypes = getByTypes;
|
|
426
|
+
module.exports.getPublished = getPublished;
|
|
427
|
+
module.exports.getWebmentionPublished = getPublished;
|
|
428
|
+
module.exports.getReceived = getReceived;
|
|
429
|
+
module.exports.getWebmentionReceived = getReceived;
|
|
430
|
+
module.exports.getContent = getContent;
|
|
431
|
+
module.exports.getWebmentionContent = getContent;
|
|
432
|
+
module.exports.getSource = getSource;
|
|
433
|
+
module.exports.getWebmentionSource = getSource;
|
|
434
|
+
module.exports.getTarget = getTarget;
|
|
435
|
+
module.exports.getWebmentionTarget = getTarget;
|
|
436
|
+
module.exports.getType = getType;
|
|
437
|
+
module.exports.getWebmentionType = getType;
|
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.3-beta.3",
|
|
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": {
|