@chrisburnell/eleventy-cache-webmentions 1.2.1 → 1.2.2

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
@@ -32,6 +32,91 @@ module.exports = function (eleventyConfig) {
32
32
 
33
33
  ## Options
34
34
 
35
+ <table>
36
+ <thead>
37
+ <tr>
38
+ <th>option</th>
39
+ <th>default value</th>
40
+ <th>description</th>
41
+ <th>version added</th>
42
+ </tr>
43
+ </thead>
44
+ <tbody>
45
+ <tr>
46
+ <td><code>domain</code><br><em>required</em></td>
47
+ <td>—</td>
48
+ <td>The website you’re fetching Webmentions for.</td>
49
+ <td>0.0.1</td>
50
+ </tr>
51
+ <tr>
52
+ <td><code>feed</code><br><em>required</em></td>
53
+ <td>—</td>
54
+ <td>The URL of your Webmention server’s feed for your <code>domain</code>.</td>
55
+ <td>0.2.0</td>
56
+ </tr>
57
+ <tr>
58
+ <td><code>key</code><br><em>required</em></td>
59
+ <td>—</td>
60
+ <td>The key in the above <code>feed</code> whose value is an Array of Webmentions.</td>
61
+ <td>0.0.1</td>
62
+ </tr>
63
+ <tr>
64
+ <td><code>directory</code></td>
65
+ <td><code>".cache"</code></td>
66
+ <td>See <a href="https://www.11ty.dev/docs/plugins/cache/#cache-directory">Eleventy Fetch’s Cache Directory</a> for more information.</td>
67
+ <td>1.1.2</td>
68
+ </tr>
69
+ <tr>
70
+ <td><code>duration</code></td>
71
+ <td><code>"1d"</code> <em>or</em> 1 day</td>
72
+ <td>See <a href="https://www.11ty.dev/docs/plugins/cache/#change-the-cache-duration">Eleventy Fetch’s Cache Duration</a> for more information.</td>
73
+ <td>0.0.1</td>
74
+ </tr>
75
+ <tr>
76
+ <td><code>uniqueKey</code></td>
77
+ <td><code>"webmentions"</code></td>
78
+ <td>The name of the file generated by Eleventy Fetch.</td>
79
+ <td>0.1.9</td>
80
+ </tr>
81
+ <tr>
82
+ <td><code>allowedHTML</code></td>
83
+ <td>See code example below</td>
84
+ <td>See the <a href="https://www.npmjs.com/package/sanitize-html">sanitize-html</a> package for more information.</td>
85
+ <td>0.0.1</td>
86
+ </tr>
87
+ <tr>
88
+ <td><code>allowlist</code></td>
89
+ <td><code>[]</code></td>
90
+ <td>An Array of root URLs from which Webmentions are kept.</td>
91
+ <td>1.1.0</td>
92
+ </tr>
93
+ <tr>
94
+ <td><code>blocklist</code></td>
95
+ <td><code>[]</code></td>
96
+ <td>An Array of root URLs from which Webmentions are discarded.</td>
97
+ <td>1.1.0</td>
98
+ </tr>
99
+ <tr>
100
+ <td><code>urlReplacements</code></td>
101
+ <td><code>{}</code></td>
102
+ <td>An Object of key-value string pairs containing from-to URL replacements on this <code>domain</code>.</td>
103
+ <td>0.0.3</td>
104
+ </tr>
105
+ <tr>
106
+ <td><code>maximumHtmlLength</code></td>
107
+ <td><code>2000</code></td>
108
+ <td>Maximum number of characters in a Webmention’s HTML content, beyond which point a different message is shown, referring to the original source.</td>
109
+ <td>0.0.1</td>
110
+ </tr>
111
+ <tr>
112
+ <td><code>maximumHtmlText</code></td>
113
+ <td><code>"mentioned this in"</code></td>
114
+ <td>The glue-y part of the message displayed when a Webmention content’s character count exceeds <code>maximumHtmlLength</code>.</td>
115
+ <td>0.1.0</td>
116
+ </tr>
117
+ </tbody>
118
+ </table>
119
+
35
120
  Advanced control over how the Webmentions are cached and processed is done by passing `options` into the plugin when using `addPlugin`:
36
121
 
37
122
  ```javascript
@@ -39,48 +124,22 @@ const pluginWebmentions = require("@chrisburnell/eleventy-cache-webmentions")
39
124
 
40
125
  module.exports = function (eleventyConfig) {
41
126
  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
127
  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
128
  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
129
  key: "children",
51
- // directory: ".cache" by default
52
- // see https://www.11ty.dev/docs/plugins/cache/#cache-directory for more info
53
130
  directory: ".cache",
54
- // duration: "1d" by default
55
- // see https://www.11ty.dev/docs/plugins/cache/#change-the-cache-duration for more info
56
131
  duration: "1d",
57
- // uniquekey: "webmentions" by default
58
- // dictates the name sent to eleventy-fetch to name the file
59
132
  uniqueKey: "webmentions",
60
- // allowedHTML: Object by default
61
- // see https://www.npmjs.com/package/sanitize-html for more info
62
133
  allowedHTML: {
63
134
  allowedTags: ["b", "i", "em", "strong", "a"],
64
135
  allowedAttributes: {
65
136
  a: ["href"],
66
137
  },
67
138
  },
68
- // allowlist: [] by default
69
- // array of root URLs from which webmentions are wanted exclusively
70
139
  allowlist: [],
71
- // blocklist: [] by default
72
- // array of root URLs from which webmentions are not wanted
73
- // exclusively
74
140
  blocklist: [],
75
- // urlReplacements: {} by default
76
- // object of key:value pairs containing from:to URL replacements
77
141
  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
142
  maximumHtmlLength: 2000,
82
- // maximumHtmlText: "mentioned this in" by default
83
- // message shown when maximumHtmlLength is reached
84
143
  maximumHtmlText: "mentioned this in",
85
144
  })
86
145
  }
@@ -7,9 +7,7 @@ const absoluteURL = (url, domain) => {
7
7
  try {
8
8
  return new URL(url, domain).toString()
9
9
  } catch (e) {
10
- console.log(
11
- `Trying to convert ${url} to be an absolute url with base ${domain} and failed.`
12
- )
10
+ console.log(`Trying to convert ${url} to be an absolute url with base ${domain} and failed.`)
13
11
  return url
14
12
  }
15
13
  }
@@ -21,13 +19,10 @@ const baseUrl = (url) => {
21
19
  }
22
20
 
23
21
  const fixUrl = (url, urlReplacements) => {
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
- )
22
+ return Object.entries(urlReplacements).reduce((accumulator, [key, value]) => {
23
+ const regex = new RegExp(key, "g")
24
+ return accumulator.replace(regex, value)
25
+ }, url)
31
26
  }
32
27
 
33
28
  const hostname = (value) => {
@@ -43,30 +38,15 @@ const epoch = (value) => {
43
38
  }
44
39
 
45
40
  const getPublished = (webmention) => {
46
- return (
47
- webmention["wm-received"] ||
48
- webmention?.["data"]["published"] ||
49
- webmention["verified_date"] ||
50
- webmention["published"]
51
- )
41
+ return webmention["wm-received"] || webmention?.["data"]["published"] || webmention["verified_date"] || webmention["published"]
52
42
  }
53
43
 
54
44
  const getContent = (webmention) => {
55
- return (
56
- webmention?.["content"]?.["html"] ||
57
- webmention?.["content"] ||
58
- webmention?.["data"]?.["content"] ||
59
- ""
60
- )
45
+ return webmention?.["content"]?.["html"] || webmention?.["content"] || webmention?.["data"]?.["content"] || ""
61
46
  }
62
47
 
63
48
  const getSource = (webmention) => {
64
- return (
65
- webmention["url"] ||
66
- webmention?.["data"]["url"] ||
67
- webmention["wm-source"] ||
68
- webmention["source"]
69
- )
49
+ return webmention["url"] || webmention?.["data"]["url"] || webmention["wm-source"] || webmention["source"]
70
50
  }
71
51
 
72
52
  const getTarget = (webmention) => {
@@ -74,14 +54,11 @@ const getTarget = (webmention) => {
74
54
  }
75
55
 
76
56
  const getType = (webmention) => {
77
- return (
78
- webmention["wm-property"] ||
79
- webmention?.["activity"]["type"] ||
80
- webmention["type"]
81
- )
57
+ return webmention["wm-property"] || webmention?.["activity"]["type"] || webmention["type"]
82
58
  }
83
59
 
84
60
  const defaults = {
61
+ duration: "1d",
85
62
  uniqueKey: "webmentions",
86
63
  allowedHTML: {
87
64
  allowedTags: ["b", "i", "em", "strong", "a"],
@@ -98,27 +75,15 @@ const defaults = {
98
75
 
99
76
  const fetchWebmentions = async (options) => {
100
77
  if (!options.domain) {
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
+ throw new Error("domain is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.")
104
79
  }
105
80
 
106
81
  if (!options.feed) {
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
+ throw new Error("feed is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.")
110
83
  }
111
84
 
112
85
  if (!options.key) {
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
- )
116
- }
117
-
118
- if (!options.uniqueKey) {
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
- )
86
+ throw new Error("key is a required field when attempting to retrieve Webmentions. See https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions#installation for more information.")
122
87
  }
123
88
 
124
89
  let asset = new AssetCache(options.uniqueKey, options.directory)
@@ -135,27 +100,16 @@ const fetchWebmentions = async (options) => {
135
100
  // results since the most recent webmention
136
101
  if (!asset.isCacheValid(options.duration)) {
137
102
  const since = webmentions.length ? getPublished(webmentions[0]) : false
138
- const url = `${options.feed}${
139
- since
140
- ? `${options.feed.includes("?") ? "&" : "?"}since=${since}`
141
- : ""
142
- }`
103
+ const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
143
104
  await fetch(url)
144
105
  .then(async (response) => {
145
106
  if (response.ok) {
146
107
  const feed = await response.json()
147
108
  if (feed[options.key].length) {
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
- )
109
+ webmentions = uniqBy([...feed[options.key], ...webmentions], (entry) => {
110
+ return getSource(entry)
111
+ })
112
+ console.log(`[${hostname(options.domain)}] ${feed[options.key].length} new Webmentions fetched into cache.`)
159
113
  }
160
114
  await asset.save(webmentions, "json")
161
115
  return webmentions
@@ -163,14 +117,7 @@ const fetchWebmentions = async (options) => {
163
117
  return Promise.reject(response)
164
118
  })
165
119
  .catch((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
- )
120
+ console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
174
121
  })
175
122
  }
176
123
 
@@ -218,12 +165,7 @@ const filteredWebmentions = async (options) => {
218
165
  // Fix local URLs based on urlReplacements and sort Webmentions into groups
219
166
  // by target base URL
220
167
  rawWebmentions.forEach((webmention) => {
221
- let url = baseUrl(
222
- fixUrl(
223
- getTarget(webmention).replace(/\/?$/, "/"),
224
- options.urlReplacements
225
- )
226
- )
168
+ let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
227
169
 
228
170
  if (!filtered[url]) {
229
171
  filtered[url] = []
@@ -239,6 +181,9 @@ const filteredWebmentions = async (options) => {
239
181
  })
240
182
  }
241
183
 
184
+ const filteredCount = Object.values(filtered).reduce((count, webmentions) => count + webmentions.length, 0)
185
+ console.log(`[${hostname(options.domain)}] ${filteredCount} filtered Webmentions pulled from cache.`)
186
+
242
187
  return filtered
243
188
  }
244
189
 
@@ -254,10 +199,7 @@ const getWebmentions = async (options, url, allowedTypes = {}) => {
254
199
  webmentions[url]
255
200
  // filter webmentions by allowed response post types
256
201
  .filter((entry) => {
257
- return typeof allowedTypes === "object" &&
258
- Object.keys(allowedTypes).length
259
- ? allowedTypes.includes(getType(entry))
260
- : true
202
+ return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
261
203
  })
262
204
  // sanitize content of webmentions against HTML limit
263
205
  .map((entry) => {
@@ -266,9 +208,7 @@ const getWebmentions = async (options, url, allowedTypes = {}) => {
266
208
  if (html.length) {
267
209
  entry.content = sanitizeHTML(html, options.allowedHTML)
268
210
  if (html.length > options.maximumHtmlLength) {
269
- entry.content = `${
270
- options.maximumHtmlText
271
- } <a href="${getSource(entry)}">${getSource(entry)}</a>`
211
+ entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
272
212
  }
273
213
  }
274
214
 
@@ -297,13 +237,7 @@ module.exports = (eleventyConfig, options = {}) => {
297
237
  // Global Data
298
238
  const filtered = async () => await filteredWebmentions(options)
299
239
  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
- )
240
+ const unfiltered = async () => await filteredWebmentions(options).then((filtered) => Object.values(filtered).reduce((array, webmentions) => [...array, ...webmentions], []))
307
241
  eleventyConfig.addGlobalData("webmentionsAll", unfiltered)
308
242
  eleventyConfig.addGlobalData("webmentions", unfiltered)
309
243
 
@@ -311,10 +245,7 @@ module.exports = (eleventyConfig, options = {}) => {
311
245
  eleventyConfig.addLiquidFilter("getWebmentions", getWebmentionsFilter)
312
246
 
313
247
  // Nunjucks Filter
314
- eleventyConfig.addNunjucksAsyncFilter(
315
- "getWebmentions",
316
- getWebmentionsFilter
317
- )
248
+ eleventyConfig.addNunjucksAsyncFilter("getWebmentions", getWebmentionsFilter)
318
249
  }
319
250
 
320
251
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrisburnell/eleventy-cache-webmentions",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Fetch and cache webmentions using eleventy-fetch.",
5
5
  "author": "Chris Burnell <me@chrisburnell.com>",
6
6
  "license": "MIT",