From 4bc168dffb20c75e2e31cbd33ff9c8e3a2157800 Mon Sep 17 00:00:00 2001
From: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
Date: Mon, 16 Feb 2026 19:11:10 +0000
Subject: [PATCH] make usernames linkable in news (#3200)
## Description:
make usernames linkable in news
now:
before:
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
w.o.n
Co-authored-by: iamlewis
---
src/client/NewsMarkdown.ts | 30 +++++++++++++++++++
src/client/NewsModal.ts | 21 +++----------
tests/client/NewsMarkdown.test.ts | 49 +++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 17 deletions(-)
create mode 100644 src/client/NewsMarkdown.ts
create mode 100644 tests/client/NewsMarkdown.test.ts
diff --git a/src/client/NewsMarkdown.ts b/src/client/NewsMarkdown.ts
new file mode 100644
index 000000000..88dcbf0ea
--- /dev/null
+++ b/src/client/NewsMarkdown.ts
@@ -0,0 +1,30 @@
+const GITHUB_PR_URL_REGEX =
+ /(?
+ `[#${prNumber}](https://github.com/openfrontio/OpenFrontIO/pull/${prNumber})`,
+ )
+ .replace(
+ GITHUB_COMPARE_URL_REGEX,
+ (_match, comparison) =>
+ `[${comparison}](https://github.com/openfrontio/OpenFrontIO/compare/${comparison})`,
+ )
+ .replace(
+ GITHUB_MENTION_REGEX,
+ (_match, prefix, username) =>
+ `${prefix}[@${username}](https://github.com/${username})`,
+ )
+ );
+}
diff --git a/src/client/NewsModal.ts b/src/client/NewsModal.ts
index fe0d622f3..dc34a06bd 100644
--- a/src/client/NewsModal.ts
+++ b/src/client/NewsModal.ts
@@ -6,6 +6,7 @@ import { translateText } from "../client/Utils";
import "./components/baseComponents/Modal";
import { BaseModal } from "./components/BaseModal";
import { modalHeader } from "./components/ui/ModalHeader";
+import { normalizeNewsMarkdown } from "./NewsMarkdown";
import changelog from "/changelog.md?url";
import megaphone from "/images/Megaphone.svg?url";
@@ -67,23 +68,9 @@ export class NewsModal extends BaseModal {
this.initialized = true;
fetch(`${changelog}?v=${encodeURIComponent(version.trim())}`)
.then((response) => (response.ok ? response.text() : "Failed to load"))
- .then((markdown) =>
- markdown
- // Convert bold header lines (e.g. "**Title**") into real Markdown headers
- // Exclude lines starting with - or * to avoid converting bullet points
- .replace(/^([^\-*\s].*?) \*\*(.+?)\*\*$/gm, "## $1 $2")
- .replace(
- /(?
- `[#${prNumber}](https://github.com/openfrontio/OpenFrontIO/pull/${prNumber})`,
- )
- .replace(
- /(?
- `[${comparison}](https://github.com/openfrontio/OpenFrontIO/compare/${comparison})`,
- ),
- )
- .then((markdown) => (this.markdown = markdown));
+ .then((markdown) => normalizeNewsMarkdown(markdown))
+ .then((markdown) => (this.markdown = markdown))
+ .catch(() => (this.markdown = "Failed to load"));
}
}
}
diff --git a/tests/client/NewsMarkdown.test.ts b/tests/client/NewsMarkdown.test.ts
new file mode 100644
index 000000000..94f83332b
--- /dev/null
+++ b/tests/client/NewsMarkdown.test.ts
@@ -0,0 +1,49 @@
+import { normalizeNewsMarkdown } from "../../src/client/NewsMarkdown";
+
+describe("normalizeNewsMarkdown", () => {
+ it("converts openfront pull request URLs to short markdown links", () => {
+ const input =
+ "Fix attack logic in https://github.com/openfrontio/OpenFrontIO/pull/1234";
+
+ const result = normalizeNewsMarkdown(input);
+
+ expect(result).toContain(
+ "[#1234](https://github.com/openfrontio/OpenFrontIO/pull/1234)",
+ );
+ });
+
+ it("converts openfront compare URLs to markdown links", () => {
+ const input =
+ "Full Changelog: https://github.com/openfrontio/OpenFrontIO/compare/v1.0.0...v1.1.0";
+
+ const result = normalizeNewsMarkdown(input);
+
+ expect(result).toContain(
+ "[v1.0.0...v1.1.0](https://github.com/openfrontio/OpenFrontIO/compare/v1.0.0...v1.1.0)",
+ );
+ });
+
+ it("converts github @mentions to profile links", () => {
+ const input = "- Feature by @evanpelle in release notes";
+
+ const result = normalizeNewsMarkdown(input);
+
+ expect(result).toContain("[@evanpelle](https://github.com/evanpelle)");
+ });
+
+ it("does not convert existing markdown-linked mentions", () => {
+ const input = "Credit [@evanpelle](https://github.com/evanpelle)";
+
+ const result = normalizeNewsMarkdown(input);
+
+ expect(result).toBe(input);
+ });
+
+ it("does not convert email addresses", () => {
+ const input = "Contact support@openfront.io for help";
+
+ const result = normalizeNewsMarkdown(input);
+
+ expect(result).toBe(input);
+ });
+});