@chrisburnell/eleventy-cache-webmentions 0.2.1 → 1.0.0-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.
@@ -2,6 +2,7 @@ const fetch = require("node-fetch")
2
2
  const sanitizeHTML = require("sanitize-html")
3
3
  const uniqBy = require("lodash/uniqBy")
4
4
  const { AssetCache } = require("@11ty/eleventy-fetch")
5
+ const { defaultsDeep } = require("lodash")
5
6
 
6
7
  const absoluteURL = (url, domain) => {
7
8
  try {
@@ -57,156 +58,164 @@ const getType = (webmention) => {
57
58
  return webmention["wm-property"] || webmention?.["activity"]["type"] || webmention["type"]
58
59
  }
59
60
 
60
- module.exports = (eleventyConfig, options = {}) => {
61
- options = Object.assign(
62
- {
63
- uniqueKey: "webmentions",
64
- allowedHTML: {
65
- allowedTags: ["b", "i", "em", "strong", "a"],
66
- allowedAttributes: {
67
- a: ["href"],
68
- },
69
- },
70
- urlReplacements: {},
71
- maximumHtmlLength: 2000,
72
- maximumHtmlText: "mentioned this in",
61
+ const defaults = {
62
+ uniqueKey: "webmentions",
63
+ allowedHTML: {
64
+ allowedTags: ["b", "i", "em", "strong", "a"],
65
+ allowedAttributes: {
66
+ a: ["href"],
73
67
  },
74
- options
75
- )
68
+ },
69
+ urlReplacements: {},
70
+ maximumHtmlLength: 2000,
71
+ maximumHtmlText: "mentioned this in",
72
+ }
76
73
 
77
- const fetchWebmentions = async () => {
78
- let asset = new AssetCache(options.uniqueKey)
79
- asset.ensureDir()
74
+ const fetchWebmentions = async (options) => {
75
+ if (!options.domain) {
76
+ 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.")
77
+ }
80
78
 
81
- let webmentions = []
79
+ if (!options.feed) {
80
+ 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.")
81
+ }
82
82
 
83
- // If there is a cached file at all, grab its contents now
84
- if (asset.isCacheValid("9001y")) {
85
- webmentions = await asset.getCachedValue()
86
- }
83
+ if (!options.key) {
84
+ 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.")
85
+ }
87
86
 
88
- // If there is a cached file but it is outside of expiry, fetch fresh
89
- // results since the most recent webmention
90
- if (!asset.isCacheValid(options.duration)) {
91
- const since = webmentions.length ? getPublished(webmentions[0]) : false
92
- const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
93
- await fetch(url)
94
- .then(async (response) => {
95
- if (response.ok) {
96
- const feed = await response.json()
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.`)
102
- }
103
- await asset.save(webmentions, "json")
104
- return webmentions
105
- }
106
- return Promise.reject(response)
107
- })
108
- .catch((error) => {
109
- console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
110
- })
111
- }
87
+ if (!options.uniqueKey) {
88
+ throw new Error("uniqueKey is a required field when adding the plugin to your eleventyConfig using addPlugin. See https://chrisburnell.com/eleventy-cache-webmentions/#installation for more information.")
89
+ }
112
90
 
113
- return webmentions
91
+ let asset = new AssetCache(options.uniqueKey)
92
+ asset.ensureDir()
93
+
94
+ let webmentions = []
95
+
96
+ // If there is a cached file at all, grab its contents now
97
+ if (asset.isCacheValid("9001y")) {
98
+ webmentions = await asset.getCachedValue()
114
99
  }
115
100
 
116
- const filteredWebmentions = async () => {
117
- const rawWebmentions = await fetchWebmentions()
118
- let webmentions = {}
101
+ // If there is a cached file but it is outside of expiry, fetch fresh
102
+ // results since the most recent webmention
103
+ if (!asset.isCacheValid(options.duration)) {
104
+ const since = webmentions.length ? getPublished(webmentions[0]) : false
105
+ const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
106
+ await fetch(url)
107
+ .then(async (response) => {
108
+ if (response.ok) {
109
+ const feed = await response.json()
110
+ if (feed[options.key].length) {
111
+ webmentions = uniqBy([...feed[options.key], ...webmentions], (entry) => {
112
+ return getSource(entry)
113
+ })
114
+ console.log(`[${hostname(options.domain)}] ${feed[options.key].length} new Webmentions fetched into cache.`)
115
+ }
116
+ await asset.save(webmentions, "json")
117
+ return webmentions
118
+ }
119
+ return Promise.reject(response)
120
+ })
121
+ .catch((error) => {
122
+ console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
123
+ })
124
+ }
119
125
 
120
- // Sort Webmentions into groups by target
121
- rawWebmentions.forEach((webmention) => {
122
- // Get the target of the Webmention and fix it up
123
- let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
126
+ return webmentions
127
+ }
124
128
 
125
- if (!webmentions[url]) {
126
- webmentions[url] = []
127
- }
129
+ const filteredWebmentions = async (options) => {
130
+ const rawWebmentions = await fetchWebmentions(options)
131
+ let webmentions = {}
128
132
 
129
- webmentions[url].push(webmention)
130
- })
133
+ // Sort Webmentions into groups by target
134
+ rawWebmentions.forEach((webmention) => {
135
+ // Get the target of the Webmention and fix it up
136
+ let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
131
137
 
132
- // Sort Webmentions in groups by url and remove duplicates by `url`
133
- for (let url in webmentions) {
134
- webmentions[url] = uniqBy(webmentions[url], (entry) => {
135
- return getSource(entry)
136
- })
138
+ if (!webmentions[url]) {
139
+ webmentions[url] = []
137
140
  }
138
141
 
139
- return webmentions
142
+ webmentions[url].push(webmention)
143
+ })
144
+
145
+ // Sort Webmentions in groups by url and remove duplicates by `url`
146
+ for (let url in webmentions) {
147
+ webmentions[url] = uniqBy(webmentions[url], (entry) => {
148
+ return getSource(entry)
149
+ })
140
150
  }
141
151
 
142
- const getWebmentions = async (url, allowedTypes = {}) => {
143
- const webmentions = await filteredWebmentions()
144
- url = absoluteURL(url, options.domain)
152
+ return webmentions
153
+ }
145
154
 
146
- if (!url || !webmentions || !webmentions[url]) {
147
- return []
148
- }
155
+ const getWebmentions = async (options, url, allowedTypes = {}) => {
156
+ const webmentions = await filteredWebmentions(options)
157
+ url = absoluteURL(url, options.domain)
149
158
 
150
- const results = webmentions[url]
151
- // filter webmentions by allowed response post types
152
- .filter((entry) => {
153
- return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
154
- })
155
- // sanitize content of webmentions against HTML limit
156
- .map((entry) => {
157
- if (!("content" in entry) || !("data" in entry)) {
158
- return entry
159
- }
160
- const html = getContent(entry)
161
- if (html && html.length > options.maximumHtmlLength) {
162
- entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
163
- } else if (Object.keys(options.allowedHTML).length) {
164
- entry.content = sanitizeHTML(html, options.allowedHTML)
165
- } else {
166
- entry.content = html
167
- }
159
+ if (!url || !webmentions || !webmentions[url]) {
160
+ return []
161
+ }
162
+
163
+ const results = webmentions[url]
164
+ // filter webmentions by allowed response post types
165
+ .filter((entry) => {
166
+ return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
167
+ })
168
+ // sanitize content of webmentions against HTML limit
169
+ .map((entry) => {
170
+ if (!("content" in entry) || !("data" in entry)) {
168
171
  return entry
169
- })
170
- // sort by published
171
- .sort((a, b) => {
172
- return epoch(getPublished(a)) - epoch(getPublished(b))
173
- })
172
+ }
173
+ const html = getContent(entry)
174
+ if (html && html.length > options.maximumHtmlLength) {
175
+ entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
176
+ } else if (Object.keys(options.allowedHTML).length) {
177
+ entry.content = sanitizeHTML(html, options.allowedHTML)
178
+ } else {
179
+ entry.content = html
180
+ }
181
+ return entry
182
+ })
183
+ // sort by published
184
+ .sort((a, b) => {
185
+ return epoch(getPublished(a)) - epoch(getPublished(b))
186
+ })
174
187
 
175
- return results
176
- }
188
+ return results
189
+ }
177
190
 
178
- const getWebmentionsFilter = async (url, allowedTypes, callback) => {
179
- if (typeof callback !== "function") {
180
- callback = allowedTypes
181
- allowedTypes = {}
182
- }
183
- const webmentions = await getWebmentions(url, allowedTypes)
184
- callback(null, webmentions)
191
+ const getWebmentionsFilter = async (options, url, allowedTypes, callback) => {
192
+ if (typeof callback !== "function") {
193
+ callback = allowedTypes
194
+ allowedTypes = {}
185
195
  }
196
+ const webmentions = await getWebmentions(options, url, allowedTypes)
197
+ callback(null, webmentions)
198
+ }
186
199
 
187
- if (eleventyConfig && options) {
188
- if (!options.domain) {
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.")
190
- }
191
-
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
- }
200
+ module.exports = (eleventyConfig, options = {}) => {
201
+ options = Object.assign(defaults, options)
195
202
 
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
- }
203
+ if (eleventyConfig) {
204
+ // Global Data
205
+ eleventyConfig.addGlobalData("webmentions", filteredWebmentions(options))
199
206
 
200
207
  // Liquid Filter
201
208
  eleventyConfig.addLiquidFilter("getWebmentions", getWebmentionsFilter)
202
209
 
203
210
  // Nunjucks Filter
204
211
  eleventyConfig.addNunjucksAsyncFilter("getWebmentions", getWebmentionsFilter)
212
+ }
205
213
 
206
- // Global Data
207
- eleventyConfig.addGlobalData("webmentions", filteredWebmentions)
208
- } else {
209
- // JavaScript
210
- return filteredWebmentions
214
+ return {
215
+ defaults: defaults,
216
+ webmentions: filteredWebmentions(options),
217
+ fetchWebmentions: fetchWebmentions,
218
+ filteredWebmentions: filteredWebmentions,
219
+ getWebmentions: getWebmentions,
211
220
  }
212
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrisburnell/eleventy-cache-webmentions",
3
- "version": "0.2.1",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "Fetch and cache webmentions using eleventy-fetch.",
5
5
  "main": "eleventy-cache-webmentions.js",
6
6
  "author": "Chris Burnell <me@chrisburnell.com>",