Skip to content

Commit 3364c51

Browse files
committed
Replace @std/html with html-entities package
- Remove @std/html dependency from deno.json - Add html-entities npm package - Replace escape() with encode() for HTML entity encoding - Replace unescape() with decode() for HTML entity decoding - Update imports across message-impl.ts, pages.tsx, session-impl.ts, and text.ts - Update test expectations for HTML entity encoding changes
1 parent 9c4281e commit 3364c51

6 files changed

Lines changed: 25 additions & 23 deletions

File tree

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
"@logtape/logtape": "jsr:@logtape/logtape@^1.0.0",
2626
"@phensley/language-tag": "npm:@phensley/language-tag@^1.12.2",
2727
"@std/assert": "jsr:@std/assert@^1.0.12",
28-
"@std/html": "jsr:@std/html@^1.0.3",
2928
"@std/media-types": "jsr:@std/media-types@^1.1.0",
3029
"hono": "jsr:@hono/hono@^4.8.2",
30+
"html-entities": "npm:html-entities@^2.6.0",
3131
"markdown-it": "npm:markdown-it@^14.1.0",
3232
"uuid": "npm:uuid@^11.1.0",
3333
"xss": "npm:xss@^1.0.15"

src/message-impl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ import {
3838
Update,
3939
} from "@fedify/fedify/vocab";
4040
import type { LanguageTag } from "@phensley/language-tag";
41-
import { unescape } from "@std/html/entities";
4241
import { parseMediaType } from "@std/media-types/parse-media-type";
42+
import { decode } from "html-entities";
4343
import { v7 as uuidv7 } from "uuid";
4444
import { FilterXSS, getDefaultWhiteList } from "xss";
4545
import type { DeferredCustomEmoji, Emoji } from "./emoji.ts";
@@ -425,7 +425,7 @@ export class AuthorizedMessageImpl<T extends MessageClass, TContextData>
425425
const objects = await Promise.all(promises);
426426
mentionedActors = objects.filter(isActor);
427427
this.html = contentHtml;
428-
this.text = unescape(textXss.process(contentHtml));
428+
this.text = decode(textXss.process(contentHtml));
429429
existingMentions = this.mentions;
430430
this.mentions = mentionedActors;
431431
this.hashtags = hashtags;
@@ -738,7 +738,7 @@ export async function createMessage<T extends MessageClass, TContextData>(
738738
language: raw.content instanceof LanguageString
739739
? raw.content.language
740740
: undefined,
741-
text: unescape(text),
741+
text: decode(text),
742742
html,
743743
replyTarget,
744744
quoteTarget,

src/pages.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import {
2626
type Object,
2727
PUBLIC_COLLECTION,
2828
} from "@fedify/fedify/vocab";
29-
import { unescape } from "@std/html/entities";
3029
import { Hono } from "hono";
30+
import { decode } from "html-entities";
3131
import type { BotImpl } from "./bot-impl.ts";
3232
import { Layout } from "./components/Layout.tsx";
3333
import { Message } from "./components/Message.tsx";
@@ -267,7 +267,7 @@ app.get("/message/:id", async (c) => {
267267
if (title == null) {
268268
title = message.summary ?? message.content;
269269
if (title != null) {
270-
title = unescape(textXss.process(title.toString()));
270+
title = decode(textXss.process(title.toString()));
271271
}
272272
}
273273
return c.html(
@@ -349,7 +349,7 @@ app.get("/feed.xml", async (c) => {
349349
if (title == null) {
350350
title = post.summary ?? post.content;
351351
if (title != null) {
352-
title = unescape(textXss.process(title.toString()));
352+
title = decode(textXss.process(title.toString()));
353353
}
354354
}
355355
return (

src/session-impl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
} from "@fedify/fedify";
2727
import { Follow, Link, Undo } from "@fedify/fedify/vocab";
2828
import { getLogger } from "@logtape/logtape";
29-
import { escape } from "@std/html/entities";
29+
import { encode } from "html-entities";
3030
import { v7 as uuidv7 } from "uuid";
3131
import type { BotImpl } from "./bot-impl.ts";
3232
import { createMessage, isMessageObject } from "./message-impl.ts";
@@ -231,8 +231,8 @@ export class SessionImpl<TContextData> implements Session<TContextData> {
231231
let url = options.quoteTarget.raw.url ?? options.quoteTarget.id;
232232
if (url instanceof Link) url = url.href ?? options.quoteTarget.id;
233233
contentHtml += `\n\n<p class="quote-inline"><br>RE: <a href="${
234-
escape(url.href)
235-
}">${escape(url.href)}</a></p>`;
234+
encode(url.href)
235+
}">${encode(url.href)}</a></p>`;
236236
tags.push(
237237
new Link({
238238
mediaType:

src/text.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ Deno.test({
258258
)}.`;
259259
assertEquals(
260260
(await Array.fromAsync(t7.getHtml(session))).join(""),
261-
'<p>Here&#39;s a link: <a href="https://fedify.dev/" target="_blank">' +
261+
'<p>Here&apos;s a link: <a href="https://fedify.dev/" target="_blank">' +
262262
"https://fedify.dev/</a>.</p>",
263263
);
264264
assertEquals(await Array.fromAsync(t7.getTags(session)), []);
@@ -269,7 +269,7 @@ Deno.test({
269269
${"First line.\nSecond line."}`;
270270
assertEquals(
271271
(await Array.fromAsync(t8.getHtml(session))).join(""),
272-
"<p>Here&#39;s a multiline text:</p><p>First line.<br>Second line.</p>",
272+
"<p>Here&apos;s a multiline text:</p><p>First line.<br>Second line.</p>",
273273
);
274274
assertEquals(await Array.fromAsync(t8.getTags(session)), []);
275275
assertEquals(t8.getCachedObjects(), []);
@@ -742,3 +742,5 @@ Deno.test("customEmoji()", async () => {
742742
// Test getCachedObjects()
743743
assertEquals(t.getCachedObjects(), []); // TemplatedText itself doesn't cache, relies on children
744744
});
745+
746+
// cSpell: ignore apos

src/text.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
mention as mentionPlugin,
2929
toFullHandle,
3030
} from "@fedify/markdown-it-mention";
31-
import { escape } from "@std/html/entities";
31+
import { encode } from "html-entities";
3232
import MarkdownIt from "markdown-it";
3333
import type { DeferredCustomEmoji } from "./emoji.ts";
3434
import type { Session } from "./session.ts";
@@ -153,7 +153,7 @@ export class TemplatedText<TContextData>
153153
paraState = "opened";
154154
}
155155
if (l > 0) yield "<br>";
156-
yield escape(line);
156+
yield encode(line);
157157
l++;
158158
}
159159
p++;
@@ -241,7 +241,7 @@ export class PlainText<TContextData> implements Text<"inline", TContextData> {
241241
let first = true;
242242
for (const line of this.text.split("\n")) {
243243
if (!first) yield "<br>";
244-
yield escape(line);
244+
yield encode(line);
245245
first = false;
246246
}
247247
}
@@ -325,18 +325,18 @@ export class MentionText<TContextData> implements Text<"inline", TContextData> {
325325
? actor.url.href
326326
: actor.url;
327327
if (url == null) {
328-
yield escape(label);
328+
yield encode(label);
329329
return;
330330
}
331331
yield '<a href="';
332-
yield escape(url.href);
332+
yield encode(url.href);
333333
yield '" translate="no" class="h-card u-url mention" target="_blank">';
334334
if (label.startsWith("@")) {
335335
yield "@<span>";
336-
yield escape(label.substring(1));
336+
yield encode(label.substring(1));
337337
yield "</span>";
338338
} else {
339-
yield escape(label);
339+
yield encode(label);
340340
}
341341
yield "</a>";
342342
}
@@ -472,9 +472,9 @@ export class HashtagText<TContextData> implements Text<"inline", TContextData> {
472472

473473
async *getHtml(session: Session<TContextData>): AsyncIterable<string> {
474474
yield '<a href="';
475-
yield escape(session.context.origin);
475+
yield encode(session.context.origin);
476476
yield "/tags/";
477-
yield escape(encodeURIComponent(this.#tag.toLowerCase()));
477+
yield encode(encodeURIComponent(this.#tag.toLowerCase()));
478478
yield '" class="mention hashtag" rel="tag" target="_blank">#<span>';
479479
yield this.#tag;
480480
yield "</span></a>";
@@ -620,7 +620,7 @@ export class LinkText<TContextData> implements Text<"inline", TContextData> {
620620

621621
async *getHtml(session: Session<TContextData>): AsyncIterable<string> {
622622
yield '<a href="';
623-
yield escape(this.#href.href);
623+
yield encode(this.#href.href);
624624
yield '" target="_blank">';
625625
yield* this.#label.getHtml(session);
626626
yield "</a>";
@@ -749,7 +749,7 @@ export class CustomEmojiText<TContextData>
749749
const emoji = this.getEmoji(session);
750750
if (emoji.name == null) return;
751751
yield "\u200b"; // zero-width space for segmentation
752-
yield escape(emoji.name.toString());
752+
yield encode(emoji.name.toString());
753753
yield "\u200b";
754754
}
755755

0 commit comments

Comments
 (0)