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; +}