@chrisburnell/eleventy-cache-webmentions 0.2.1 → 1.0.0-beta.1

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,157 @@ 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
+ let asset = new AssetCache(options.uniqueKey)
76
+ asset.ensureDir()
80
77
 
81
- let webmentions = []
78
+ let webmentions = []
82
79
 
83
- // If there is a cached file at all, grab its contents now
84
- if (asset.isCacheValid("9001y")) {
85
- webmentions = await asset.getCachedValue()
86
- }
80
+ // If there is a cached file at all, grab its contents now
81
+ if (asset.isCacheValid("9001y")) {
82
+ webmentions = await asset.getCachedValue()
83
+ }
87
84
 
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
85
+ // If there is a cached file but it is outside of expiry, fetch fresh
86
+ // results since the most recent webmention
87
+ if (!asset.isCacheValid(options.duration)) {
88
+ const since = webmentions.length ? getPublished(webmentions[0]) : false
89
+ const url = `${options.feed}${since ? `${options.feed.includes("?") ? "&" : "?"}since=${since}` : ""}`
90
+ await fetch(url)
91
+ .then(async (response) => {
92
+ if (response.ok) {
93
+ const feed = await response.json()
94
+ if (feed[options.key].length) {
95
+ webmentions = uniqBy([...feed[options.key], ...webmentions], (entry) => {
96
+ return getSource(entry)
97
+ })
98
+ console.log(`[${hostname(options.domain)}] ${feed[options.key].length} new Webmentions fetched into cache.`)
105
99
  }
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
- }
112
-
113
- return webmentions
100
+ await asset.save(webmentions, "json")
101
+ return webmentions
102
+ }
103
+ return Promise.reject(response)
104
+ })
105
+ .catch((error) => {
106
+ console.log(`[${hostname(options.domain)}] Something went wrong with your request to ${hostname(options.feed)}!`, error)
107
+ })
114
108
  }
115
109
 
116
- const filteredWebmentions = async () => {
117
- const rawWebmentions = await fetchWebmentions()
118
- let webmentions = {}
119
-
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))
110
+ return webmentions
111
+ }
124
112
 
125
- if (!webmentions[url]) {
126
- webmentions[url] = []
127
- }
113
+ const filteredWebmentions = async (options) => {
114
+ const rawWebmentions = await fetchWebmentions(options)
115
+ let webmentions = {}
128
116
 
129
- webmentions[url].push(webmention)
130
- })
117
+ // Sort Webmentions into groups by target
118
+ rawWebmentions.forEach((webmention) => {
119
+ // Get the target of the Webmention and fix it up
120
+ let url = baseUrl(fixUrl(getTarget(webmention).replace(/\/?$/, "/"), options.urlReplacements))
131
121
 
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
- })
122
+ if (!webmentions[url]) {
123
+ webmentions[url] = []
137
124
  }
138
125
 
139
- return webmentions
126
+ webmentions[url].push(webmention)
127
+ })
128
+
129
+ // Sort Webmentions in groups by url and remove duplicates by `url`
130
+ for (let url in webmentions) {
131
+ webmentions[url] = uniqBy(webmentions[url], (entry) => {
132
+ return getSource(entry)
133
+ })
140
134
  }
141
135
 
142
- const getWebmentions = async (url, allowedTypes = {}) => {
143
- const webmentions = await filteredWebmentions()
144
- url = absoluteURL(url, options.domain)
136
+ return webmentions
137
+ }
145
138
 
146
- if (!url || !webmentions || !webmentions[url]) {
147
- return []
148
- }
139
+ const getWebmentions = async (options, url, allowedTypes = {}) => {
140
+ const webmentions = await filteredWebmentions(options)
141
+ url = absoluteURL(url, options.domain)
149
142
 
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
- }
143
+ if (!url || !webmentions || !webmentions[url]) {
144
+ return []
145
+ }
146
+
147
+ const results = webmentions[url]
148
+ // filter webmentions by allowed response post types
149
+ .filter((entry) => {
150
+ return typeof allowedTypes === "object" && Object.keys(allowedTypes).length ? allowedTypes.includes(getType(entry)) : true
151
+ })
152
+ // sanitize content of webmentions against HTML limit
153
+ .map((entry) => {
154
+ if (!("content" in entry) || !("data" in entry)) {
168
155
  return entry
169
- })
170
- // sort by published
171
- .sort((a, b) => {
172
- return epoch(getPublished(a)) - epoch(getPublished(b))
173
- })
156
+ }
157
+ const html = getContent(entry)
158
+ if (html && html.length > options.maximumHtmlLength) {
159
+ entry.content = `${options.maximumHtmlText} <a href="${getSource(entry)}">${getSource(entry)}</a>`
160
+ } else if (Object.keys(options.allowedHTML).length) {
161
+ entry.content = sanitizeHTML(html, options.allowedHTML)
162
+ } else {
163
+ entry.content = html
164
+ }
165
+ return entry
166
+ })
167
+ // sort by published
168
+ .sort((a, b) => {
169
+ return epoch(getPublished(a)) - epoch(getPublished(b))
170
+ })
174
171
 
175
- return results
172
+ return results
173
+ }
174
+
175
+ const getWebmentionsFilter = async (options, url, allowedTypes, callback) => {
176
+ if (typeof callback !== "function") {
177
+ callback = allowedTypes
178
+ allowedTypes = {}
176
179
  }
180
+ const webmentions = await getWebmentions(options, url, allowedTypes)
181
+ callback(null, webmentions)
182
+ }
177
183
 
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)
184
+ module.exports = (eleventyConfig, options = {}) => {
185
+ options = Object.assign(defaults, options)
186
+
187
+ if (!options.domain) {
188
+ 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.")
185
189
  }
186
190
 
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
+ if (!options.feed) {
192
+ 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.")
193
+ }
191
194
 
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
- }
195
+ if (!options.key) {
196
+ 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.")
197
+ }
195
198
 
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
- }
199
+ if (eleventyConfig) {
200
+ // Global Data
201
+ eleventyConfig.addGlobalData("webmentions", filteredWebmentions(options))
199
202
 
200
203
  // Liquid Filter
201
204
  eleventyConfig.addLiquidFilter("getWebmentions", getWebmentionsFilter)
202
205
 
203
206
  // Nunjucks Filter
204
207
  eleventyConfig.addNunjucksAsyncFilter("getWebmentions", getWebmentionsFilter)
208
+ }
205
209
 
206
- // Global Data
207
- eleventyConfig.addGlobalData("webmentions", filteredWebmentions)
208
- } else {
209
- // JavaScript
210
- return filteredWebmentions
210
+ return {
211
+ webmentions: filteredWebmentions(options),
212
+ getWebmentions: getWebmentions,
211
213
  }
212
214
  }
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.1",
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>",