diff --git a/apps/frontend/src/components/ui/servers/LogParser.vue b/apps/frontend/src/components/ui/servers/LogParser.vue
index 69e48e2de..912d1f3f1 100644
--- a/apps/frontend/src/components/ui/servers/LogParser.vue
+++ b/apps/frontend/src/components/ui/servers/LogParser.vue
@@ -37,19 +37,34 @@ const convert = new Convert({
fg: "#FFF",
bg: "#000",
newline: false,
- escapeXML: false,
+ escapeXML: true,
stream: false,
colors,
});
-const parsedLog = computed(() => {
- return convert.toHtml(props.log);
-});
+const urlRegex = /https?:\/\/[^\s]+/g;
+const usernameRegex = /<([^&]+)>/g;
const sanitizedLog = computed(() => {
- return DOMPurify.sanitize(parsedLog.value, {
- ALLOWED_TAGS: ["span"],
- ALLOWED_ATTR: ["style"],
+ let html = convert.toHtml(props.log);
+
+ html = html.replace(
+ urlRegex,
+ (url) =>
+ `${url}`,
+ );
+
+ html = html.replace(
+ usernameRegex,
+ (_, username) => `<${username}>`,
+ );
+
+ return DOMPurify.sanitize(html, {
+ ALLOWED_TAGS: ["span", "a"],
+ ALLOWED_ATTR: ["style", "href", "target", "rel", "class"],
+ ADD_ATTR: ["target"],
+ RETURN_TRUSTED_TYPE: true,
+ USE_PROFILES: { html: true },
});
});
@@ -66,4 +81,8 @@ html.dark-mode .parsed-log:hover {
html.oled-mode .parsed-log:hover {
background-color: #333;
}
+
+.minecraft-username {
+ font-weight: bold;
+}