@evanp/activitypub-bot 0.46.0 → 0.46.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.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,12 @@ and this project adheres to
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.46.1] - 2026-05-25
13
+
14
+ ### Fixed
15
+
16
+ - Better escaping for Webfinger, Hashtags, and URLs in HTML output
17
+
12
18
  ## [0.46.0] - 2026-05-25
13
19
 
14
20
  ### Added
@@ -26,12 +26,7 @@ export class Transformer {
26
26
  }
27
27
 
28
28
  async transform (text) {
29
- let html = text
30
- .replace(/&/g, '&')
31
- .replace(/</g, '&lt;')
32
- .replace(/>/g, '&gt;')
33
- .replace(/"/g, '&quot;')
34
- .replace(/'/g, '&apos;')
29
+ let html = this.#escape(text)
35
30
  let tag = [];
36
31
  ({ html, tag } = this.#replaceUrls(html, tag));
37
32
  ({ html, tag } = this.#replaceHashtags(html, tag));
@@ -47,7 +42,8 @@ export class Transformer {
47
42
  const segment = segments[i]
48
43
  if (this.#isLink(segment)) continue
49
44
  segments[i] = segment.replace(url, (match) => {
50
- return `<a href="${match}">${match}</a>`
45
+ const escaped = this.#escape(match)
46
+ return `<a href="${escaped}">${escaped}</a>`
51
47
  })
52
48
  }
53
49
  return { html: segments.join(''), tag }
@@ -62,7 +58,9 @@ export class Transformer {
62
58
  segments[i] = segment.replace(hashtag, (match, name) => {
63
59
  const href = this.#tagNamespace + name
64
60
  tag.push({ type: AS2 + 'Hashtag', name: match, href })
65
- return `<a href="${href}">${match}</a>`
61
+ const escaped = this.#escape(href)
62
+ const escapedMatch = this.#escape(match)
63
+ return `<a href="${escaped}">${escapedMatch}</a>`
66
64
  })
67
65
  }
68
66
  return { html: segments.join(''), tag }
@@ -78,8 +76,19 @@ export class Transformer {
78
76
  segments[i] = await this.#replaceAsync(segments[i], webfinger, async (match) => {
79
77
  const href = await self.#homePage(match.slice(1))
80
78
  if (!href) return match
81
- tag.push({ type: 'Mention', name: match, href })
82
- return `<a href="${href}">${match}</a>`
79
+ let url
80
+ try {
81
+ url = new URL(href)
82
+ } catch (err) {
83
+ return match
84
+ }
85
+ if (url.protocol !== 'https:') {
86
+ return match
87
+ }
88
+ tag.push({ type: 'Mention', name: match, href: url.href })
89
+ const escaped = this.#escape(url.href)
90
+ const escapedMatch = this.#escape(match)
91
+ return `<a href="${escaped}">${escapedMatch}</a>`
83
92
  })
84
93
  }
85
94
  return { html: segments.join(''), tag }
@@ -157,4 +166,13 @@ export class Transformer {
157
166
  // Replace the matches with their respective replacements
158
167
  return str.replace(regex, () => replacements.shift())
159
168
  }
169
+
170
+ #escape (text) {
171
+ return text
172
+ .replace(/&/g, '&amp;')
173
+ .replace(/</g, '&lt;')
174
+ .replace(/>/g, '&gt;')
175
+ .replace(/"/g, '&quot;')
176
+ .replace(/'/g, '&apos;')
177
+ }
160
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evanp/activitypub-bot",
3
- "version": "0.46.0",
3
+ "version": "0.46.1",
4
4
  "description": "server-side ActivityPub bot framework",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",