@chrisburnell/eleventy-cache-webmentions 1.1.4 → 1.2.0

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 CHANGED
@@ -21,12 +21,12 @@ Inside your Eleventy config file (typically `.eleventy.js`), use `addPlugin`:
21
21
  const pluginWebmentions = require("@chrisburnell/eleventy-cache-webmentions")
22
22
 
23
23
  module.exports = function (eleventyConfig) {
24
- eleventyConfig.addPlugin(pluginWebmentions, {
25
- // these 3 fields are all required!
26
- domain: "https://example.com",
27
- feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
28
- key: "children",
29
- })
24
+ eleventyConfig.addPlugin(pluginWebmentions, {
25
+ // these 3 fields are all required!
26
+ domain: "https://example.com",
27
+ feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
28
+ key: "children",
29
+ })
30
30
  }
31
31
  ```
32
32
 
@@ -38,51 +38,51 @@ Advanced control over how the Webmentions are cached and processed is done by pa
38
38
  const pluginWebmentions = require("@chrisburnell/eleventy-cache-webmentions")
39
39
 
40
40
  module.exports = function (eleventyConfig) {
41
- eleventyConfig.addPlugin(pluginWebmentions, {
42
- // domain: required or the plugin will not function
43
- // this is the website that you want to pull in Webmentions for
44
- domain: "https://example.com",
45
- // feed: required or the plugin will not function
46
- // defines the URL of your Webmention server where a feed of Webmentions for your domain can be found
47
- feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
48
- // key: required or the plugin will not function
49
- // dictates the key inside the feed where the array of Webmentions is located
50
- key: "children",
51
- // directory: ".cache" by default
52
- // see https://www.11ty.dev/docs/plugins/cache/#cache-directory for more info
53
- directory: ".cache",
54
- // duration: "1d" by default
55
- // see https://www.11ty.dev/docs/plugins/cache/#change-the-cache-duration for more info
56
- duration: "1d",
57
- // uniquekey: "webmentions" by default
58
- // dictates the name sent to eleventy-fetch to name the file
59
- uniqueKey: "webmentions",
60
- // allowedHTML: Object by default
61
- // see https://www.npmjs.com/package/sanitize-html for more info
62
- allowedHTML: {
63
- allowedTags: ["b", "i", "em", "strong", "a"],
64
- allowedAttributes: {
65
- a: ["href"],
66
- },
67
- },
68
- // allowlist: [] by default
69
- // array of root URLs from which webmentions are wanted exclusively
70
- allowlist: [],
71
- // blocklist: [] by default
72
- // array of root URLs from which webmentions are not wanted
73
- // exclusively
74
- blocklist: [],
75
- // urlReplacements: {} by default
76
- // object of key:value pairs containing from:to URL replacements
77
- urlReplacements: {},
78
- // maximumHtmlLength: 2000 by default
79
- // number of characters in the HTML content at which a different
80
- // message is shown instead of the content
81
- maximumHtmlLength: 2000,
82
- // maximumHtmlText: "mentioned this in" by default
83
- // message shown when maximumHtmlLength is reached
84
- maximumHtmlText: "mentioned this in",
85
- })
41
+ eleventyConfig.addPlugin(pluginWebmentions, {
42
+ // domain: required or the plugin will not function
43
+ // this is the website that you want to pull in Webmentions for
44
+ domain: "https://example.com",
45
+ // feed: required or the plugin will not function
46
+ // defines the URL of your Webmention server where a feed of Webmentions for your domain can be found
47
+ feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
48
+ // key: required or the plugin will not function
49
+ // dictates the key inside the feed where the array of Webmentions is located
50
+ key: "children",
51
+ // directory: ".cache" by default
52
+ // see https://www.11ty.dev/docs/plugins/cache/#cache-directory for more info
53
+ directory: ".cache",
54
+ // duration: "1d" by default
55
+ // see https://www.11ty.dev/docs/plugins/cache/#change-the-cache-duration for more info
56
+ duration: "1d",
57
+ // uniquekey: "webmentions" by default
58
+ // dictates the name sent to eleventy-fetch to name the file
59
+ uniqueKey: "webmentions",
60
+ // allowedHTML: Object by default
61
+ // see https://www.npmjs.com/package/sanitize-html for more info
62
+ allowedHTML: {
63
+ allowedTags: ["b", "i", "em", "strong", "a"],
64
+ allowedAttributes: {
65
+ a: ["href"],
66
+ },
67
+ },
68
+ // allowlist: [] by default
69
+ // array of root URLs from which webmentions are wanted exclusively
70
+ allowlist: [],
71
+ // blocklist: [] by default
72
+ // array of root URLs from which webmentions are not wanted
73
+ // exclusively
74
+ blocklist: [],
75
+ // urlReplacements: {} by default
76
+ // object of key:value pairs containing from:to URL replacements
77
+ urlReplacements: {},
78
+ // maximumHtmlLength: 2000 by default
79
+ // number of characters in the HTML content at which a different
80
+ // message is shown instead of the content
81
+ maximumHtmlLength: 2000,
82
+ // maximumHtmlText: "mentioned this in" by default
83
+ // message shown when maximumHtmlLength is reached
84
+ maximumHtmlText: "mentioned this in",
85
+ })
86
86
  }
87
87
  ```
88
88
 
@@ -92,9 +92,9 @@ Accessing the plugin in JavaScript in the way shown below will give you an Objec
92
92
 
93
93
  ```javascript
94
94
  const Webmentions = require("@chrisburnell/eleventy-cache-webmentions")(null, {
95
- domain: "https://example.com",
96
- feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
97
- key: "children",
95
+ domain: "https://example.com",
96
+ feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
97
+ key: "children",
98
98
  })
99
99
 
100
100
  const webmentionsByUrl = await Webmentions()
@@ -104,28 +104,28 @@ This can prove to be very useful when building out your pages. Using [Eleventy
104
104
 
105
105
  ```javascript
106
106
  const Webmentions = require("@chrisburnell/eleventy-cache-webmentions")(null, {
107
- domain: "https://example.com",
108
- feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
109
- key: "children",
107
+ domain: "https://example.com",
108
+ feed: "https://webmentions.example.com?token=S3cr3tT0k3n",
109
+ key: "children",
110
110
  })
111
111
 
112
112
  module.exports = async () => {
113
- const webmentionsByUrl = await Webmentions()
114
-
115
- return {
116
- eleventyComputed: {
117
- webmentions: (data) => {
118
- const webmentionsForUrl = webmentionsByUrl["https://example.com" + data.page.url] || []
119
-
120
- if (webmentionsForUrl.length) {
121
- return webmentionsForUrl.sort((a, b) => {
122
- return (b.data.published || b.verified_date) - (a.data.published || a.verified_date)
123
- })
124
- }
125
- return []
126
- },
127
- },
128
- }
113
+ const webmentionsByUrl = await Webmentions()
114
+
115
+ return {
116
+ eleventyComputed: {
117
+ webmentions: (data) => {
118
+ const webmentionsForUrl = webmentionsByUrl["https://example.com" + data.page.url] || []
119
+
120
+ if (webmentionsForUrl.length) {
121
+ return webmentionsForUrl.sort((a, b) => {
122
+ return (b.data.published || b.verified_date) - (a.data.published || a.verified_date)
123
+ })
124
+ }
125
+ return []
126
+ },
127
+ },
128
+ }
129
129
  }
130
130
  ```
131
131
 
@@ -133,11 +133,11 @@ You can now use this data in a number of useful ways, not limited to things like
133
133
 
134
134
  ```javascript
135
135
  module.exports = (eleventyConfig) => {
136
- eleventyConfig.addCollection("popular", (collection) => {
137
- return collection.sort((a, b) => {
138
- return b.data.webmentions.length - a.data.webmentions.length
139
- })
140
- })
136
+ eleventyConfig.addCollection("popular", (collection) => {
137
+ return collection.sort((a, b) => {
138
+ return b.data.webmentions.length - a.data.webmentions.length
139
+ })
140
+ })
141
141
  }
142
142
  ```
143
143
 
@@ -166,7 +166,7 @@ And, if you need it, the entire Object of sorted Webmentions is available too:
166
166
 
167
167
  ```twig
168
168
  {% raw %}{% set count = 0 %}
169
- {% for url, array in webmentions %}
169
+ {% for url, array in webmentionsAll %}
170
170
  {% set count = array.length + count %}
171
171
  {% endfor %}
172
172
  <p>This site has received {{ count }} Webmentions!</p>{% endraw %}
@@ -190,11 +190,11 @@ WEBMENTION_IO_TOKEN=njJql0lKXnotreal4x3Wmd
190
190
  const pluginWebmentions = require("@chrisburnell/eleventy-cache-webmentions")
191
191
 
192
192
  module.exports = function (eleventyConfig) {
193
- eleventyConfig.addPlugin(pluginWebmentions, {
194
- domain: "https://example.com",
195
- feed: `https://webmention.io/api/mentions.jf2?domain=example.com&per-page=9001&token=${process.env.WEBMENTION_IO_TOKEN}`,
196
- key: "children",
197
- })
193
+ eleventyConfig.addPlugin(pluginWebmentions, {
194
+ domain: "https://example.com",
195
+ feed: `https://webmention.io/api/mentions.jf2?domain=example.com&per-page=9001&token=${process.env.WEBMENTION_IO_TOKEN}`,
196
+ key: "children",
197
+ })
198
198
  }
199
199
  ```
200
200
 
@@ -216,11 +216,11 @@ GO_JAMMING_TOKEN=njJql0lKXnotreal4x3Wmd
216
216
  const pluginWebmentions = require("@chrisburnell/eleventy-cache-webmentions")
217
217
 
218
218
  module.exports = function (eleventyConfig) {
219
- eleventyConfig.addPlugin(pluginWebmentions, {
220
- domain: "https://example.com",
221
- feed: `https://jam.example.com/webmention/example.com/${process.env.GO_JAMMING_TOKEN}`,
222
- key: "json",
223
- })
219
+ eleventyConfig.addPlugin(pluginWebmentions, {
220
+ domain: "https://example.com",
221
+ feed: `https://jam.example.com/webmention/example.com/${process.env.GO_JAMMING_TOKEN}`,
222
+ key: "json",
223
+ })
224
224
  }
225
225
  ```
226
226
 
@@ -7,7 +7,9 @@ const absoluteURL = (url, domain) => {
7
7
  try {
8
8
  return new URL(url, domain).toString()
9
9
  } catch (e) {
10
- console.log(`Trying to convert ${url} to be an absolute url with base ${domain} and failed.`)
10
+ console.log(
11
+ `Trying to convert ${url} to be an absolute url with base ${domain} and failed.`
12
+ )
11
13
  return url
12
14
  }
13
15
  }
@@ -19,10 +21,13 @@ const baseUrl = (url) => {
19
21
  }
20
22
 
21
23
  const fixUrl = (url, urlReplacements) => {
22
- return Object.entries(urlReplacements).reduce((accumulator, [key, value]) => {
23
- const regex = new RegExp(key, "g")
24
- return accumulator.replace(regex, value)
25
- }, url)
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
+ )
26
31
  }
27
32
 
28
33
  const hostname = (value) => {
@@ -38,15 +43,30 @@ const epoch = (value) => {
38
43
  }
39
44
 
40
45
  const getPublished = (webmention) => {
41
- return webmention["wm-received"] || webmention?.["data"]["published"] || webmention["verified_date"] || webmention["published"]
46
+ return (
47
+ webmention["wm-received"] ||
48
+ webmention?.["data"]["published"] ||
49
+ webmention["verified_date"] ||
50
+ webmention["published"]
51
+ )
42
52
  }
43
53
 
44
54
  const getContent = (webmention) => {
45
- return webmention?.["content"]?.["html"] || webmention?.["content"] || webmention?.["data"]?.["content"] || ""
55
+ return (
56
+ webmention?.["content"]?.["html"] ||
57
+ webmention?.["content"] ||
58
+ webmention?.["data"]?.["content"] ||
59
+ ""
60
+ )
46
61
  }
47
62
 
48
63
  const getSource = (webmention) => {
49
- return webmention["url"] || webmention?.["data"]["url"] || webmention["wm-source"] || webmention["source"]
64
+ return (
65
+ webmention["url"] ||
66
+ webmention?.["data"]["url"] ||
67
+ webmention["wm-source"] ||
68
+ webmention["source"]
69
+ )
50
70
  }
51
71
 
52
72
  const getTarget = (webmention) => {
@@ -54,7 +74,11 @@ const getTarget = (webmention) => {
54
74
  }
55
75
 
56
76
  const getType = (webmention) => {
57
- return webmention["wm-property"] || webmention?.["activity"]["type"] || webmention["type"]
77
+ return (
78
+ webmention["wm-property"] ||
79
+ webmention?.["activity"]["type"] ||
80
+ webmention["type"]
81
+ )
58
82
  }
59
83
 
60
84
  const defaults = {
@@ -74,19 +98,27 @@ const defaults = {
74
98
 
75
99
  const fetchWebmentions = async (options) => {
76
100
  if (!options.domain) {
77
- throw new Error("domain is a required field when attempting to retrieve Webmentions. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
101
+ throw new Error(
102
+ "domain is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information."
103
+ )
78
104
  }
79
105
 
80
106
  if (!options.feed) {
81
- throw new Error("feed is a required field when attempting to retrieve Webmentions. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
107
+ throw new Error(
108
+ "feed is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information."
109
+ )
82
110
  }
83
111
 
84
112
  if (!options.key) {
85
- throw new Error("key is a required field when attempting to retrieve Webmentions. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
113
+ throw new Error(
114
+ "key is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information."
115
+ )
86
116
  }
87
117
 
88
118
  if (!options.uniqueKey) {
89
- throw new Error("uniqueKey is a required field when attempting to retrieve Webmentions. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
119
+ throw new Error(
120
+ "uniqueKey is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information."
121
+ )
90
122
  }
91
123
 
92
124
  let asset = new AssetCache(options.uniqueKey, options.directory)
@@ -103,16 +135,27 @@ const fetchWebmentions = async (options) => {
103
135
  // results since the most recent webmention
104
136
  if (!asset.isCacheValid(options.duration)) {
105
137
  const since = webmentions.length ? getPublished(webmentions[0]) : false
106
- const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
138
+ const url = `${options.feed}${
139
+ since
140
+ ? `${options.feed.includes("?") ? "&" : "?"}since=${since}`
141
+ : ""
142
+ }`
107
143
  await fetch(url)
108
144
  .then(async (response) => {
109
145
  if (response.ok) {
110
146
  const feed = await response.json()
111
147
  if (feed[options.key].length) {
112
- webmentions = uniqBy([...feed[options.key], ...webmentions], (entry) => {
113
- return getSource(entry)
114
- })
115
- console.log(`[${hostname(options.domain)}] ${feed[options.key].length} new Webmentions fetched into cache.`)
148
+ webmentions = uniqBy(
149
+ [...feed[options.key], ...webmentions],
150
+ (entry) => {
151
+ return getSource(entry)
152
+ }
153
+ )
154
+ console.log(
155
+ `[${hostname(options.domain)}] ${
156
+ feed[options.key].length
157
+ } new Webmentions fetched into cache.`
158
+ )
116
159
  }
117
160
  await asset.save(webmentions, "json")
118
161
  return webmentions
@@ -120,16 +163,27 @@ const fetchWebmentions = async (options) => {
120
163
  return Promise.reject(response)
121
164
  })
122
165
  .catch((error) => {
123
- console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
166
+ console.log(
167
+ `[${hostname(
168
+ options.domain
169
+ )}] Something went wrong with your request to ${hostname(
170
+ options.feed
171
+ )}!`,
172
+ error
173
+ )
124
174
  })
125
175
  }
126
176
 
127
177
  return webmentions
128
178
  }
129
179
 
180
+ let filtered = {}
130
181
  const filteredWebmentions = async (options) => {
182
+ if (Object.entries(filtered).length) {
183
+ return filtered
184
+ }
185
+
131
186
  let rawWebmentions = await fetchWebmentions(options)
132
- let webmentions = {}
133
187
 
134
188
  // Process the blocklist, if it has any entries
135
189
  if (options.blocklist.length) {
@@ -164,23 +218,28 @@ const filteredWebmentions = async (options) => {
164
218
  // Fix local URLs based on urlReplacements and sort Webmentions into groups
165
219
  // by target base URL
166
220
  rawWebmentions.forEach((webmention) => {
167
- let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
168
-
169
- if (!webmentions[url]) {
170
- webmentions[url] = []
221
+ let url = baseUrl(
222
+ fixUrl(
223
+ getTarget(webmention).replace(/\/?$/, "/"),
224
+ options.urlReplacements
225
+ )
226
+ )
227
+
228
+ if (!filtered[url]) {
229
+ filtered[url] = []
171
230
  }
172
231
 
173
- webmentions[url].push(webmention)
232
+ filtered[url].push(webmention)
174
233
  })
175
234
 
176
235
  // Remove duplicates by source URL
177
- for (let url in webmentions) {
178
- webmentions[url] = uniqBy(webmentions[url], (entry) => {
236
+ for (let url in filtered) {
237
+ filtered[url] = uniqBy(filtered[url], (entry) => {
179
238
  return getSource(entry)
180
239
  })
181
240
  }
182
241
 
183
- return webmentions
242
+ return filtered
184
243
  }
185
244
 
186
245
  const getWebmentions = async (options, url, allowedTypes = {}) => {
@@ -195,7 +254,10 @@ const getWebmentions = async (options, url, allowedTypes = {}) => {
195
254
  webmentions[url]
196
255
  // filter webmentions by allowed response post types
197
256
  .filter((entry) => {
198
- return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
257
+ return typeof allowedTypes === "object" &&
258
+ Object.keys(allowedTypes).length
259
+ ? allowedTypes.includes(getType(entry))
260
+ : true
199
261
  })
200
262
  // sanitize content of webmentions against HTML limit
201
263
  .map((entry) => {
@@ -204,7 +266,9 @@ const getWebmentions = async (options, url, allowedTypes = {}) => {
204
266
  if (html.length) {
205
267
  entry.content = sanitizeHTML(html, options.allowedHTML)
206
268
  if (html.length > options.maximumHtmlLength) {
207
- entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
269
+ entry.content = `${
270
+ options.maximumHtmlText
271
+ } <a href="${getSource(entry)}">${getSource(entry)}</a>`
208
272
  }
209
273
  }
210
274
 
@@ -231,13 +295,26 @@ module.exports = (eleventyConfig, options = {}) => {
231
295
 
232
296
  if (eleventyConfig) {
233
297
  // Global Data
234
- eleventyConfig.addGlobalData("webmentions", filteredWebmentions(options))
298
+ const filtered = async () => await filteredWebmentions(options)
299
+ eleventyConfig.addGlobalData("webmentionsByUrl", filtered)
300
+ const unfiltered = async () =>
301
+ await filteredWebmentions(options).then((filtered) =>
302
+ Object.values(filtered).reduce(
303
+ (array, webmentions) => [...array, ...webmentions],
304
+ []
305
+ )
306
+ )
307
+ eleventyConfig.addGlobalData("webmentionsAll", unfiltered)
308
+ eleventyConfig.addGlobalData("webmentions", unfiltered)
235
309
 
236
310
  // Liquid Filter
237
311
  eleventyConfig.addLiquidFilter("getWebmentions", getWebmentionsFilter)
238
312
 
239
313
  // Nunjucks Filter
240
- eleventyConfig.addNunjucksAsyncFilter("getWebmentions", getWebmentionsFilter)
314
+ eleventyConfig.addNunjucksAsyncFilter(
315
+ "getWebmentions",
316
+ getWebmentionsFilter
317
+ )
241
318
  }
242
319
 
243
320
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrisburnell/eleventy-cache-webmentions",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "Fetch and cache webmentions using eleventy-fetch.",
5
5
  "author": "Chris Burnell <me@chrisburnell.com>",
6
6
  "license": "MIT",
@@ -20,13 +20,13 @@
20
20
  "webmention"
21
21
  ],
22
22
  "devDependencies": {
23
- "eslint": "^8.7.0"
23
+ "eslint": "^8.41.0"
24
24
  },
25
25
  "dependencies": {
26
- "@11ty/eleventy-fetch": "^3.0.0",
26
+ "@11ty/eleventy-fetch": "^4.0.0",
27
27
  "lodash": "^4.17.21",
28
- "node-fetch": "^2.6.5",
29
- "sanitize-html": "^2.7.1"
28
+ "node-fetch": "^3.3.1",
29
+ "sanitize-html": "^2.10.0"
30
30
  },
31
31
  "main": "eleventy-cache-webmentions.js",
32
32
  "scripts": {