mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-13 22:53:12 +00:00
Fix: fixed zalgo text + html formatting inside of the review message
This commit is contained in:
@@ -15,6 +15,7 @@ import { EditGameModal, DeleteReviewModal } from "./modals";
|
||||
import { ReviewSortOptions } from "./review-sort-options";
|
||||
import { ReviewPromptBanner } from "./review-prompt-banner";
|
||||
|
||||
import { sanitizeHtml } from "@shared";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { cloudSyncContext, gameDetailsContext } from "@renderer/context";
|
||||
import { AuthPage } from "@shared";
|
||||
@@ -123,7 +124,12 @@ export function GameDetailsContent() {
|
||||
|
||||
// Tiptap editor for review input
|
||||
const editor = useEditor({
|
||||
extensions: [StarterKit],
|
||||
extensions: [
|
||||
StarterKit.configure({
|
||||
// Disable link extension to prevent automatic link rendering and XSS
|
||||
link: false,
|
||||
}),
|
||||
],
|
||||
content: "",
|
||||
editorProps: {
|
||||
attributes: {
|
||||
@@ -739,7 +745,7 @@ export function GameDetailsContent() {
|
||||
<div
|
||||
className="game-details__review-content"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: review.reviewHtml,
|
||||
__html: sanitizeHtml(review.reviewHtml),
|
||||
}}
|
||||
/>
|
||||
<div className="game-details__review-actions">
|
||||
|
||||
@@ -200,6 +200,8 @@ $hero-height: 300px;
|
||||
border-radius: 6px;
|
||||
padding: calc(globals.$spacing-unit * 2);
|
||||
margin-bottom: calc(globals.$spacing-unit * 2);
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
&__review-header {
|
||||
@@ -233,6 +235,7 @@ $hero-height: 300px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: globals.$small-font-size;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
|
||||
&--clickable {
|
||||
cursor: pointer;
|
||||
@@ -383,6 +386,11 @@ $hero-height: 300px;
|
||||
&__review-content {
|
||||
color: globals.$body-color;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&__reviews-loading {
|
||||
|
||||
41
src/shared/html-sanitizer.ts
Normal file
41
src/shared/html-sanitizer.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
function removeZalgoText(text: string): string {
|
||||
const zalgoRegex = /[\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/g;
|
||||
|
||||
return text.replace(zalgoRegex, '');
|
||||
}
|
||||
|
||||
export function sanitizeHtml(html: string): string {
|
||||
if (!html || typeof html !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
let cleanText = html.replace(/<[^>]*>/g, '');
|
||||
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = cleanText;
|
||||
cleanText = tempDiv.textContent || tempDiv.innerText || '';
|
||||
|
||||
cleanText = removeZalgoText(cleanText);
|
||||
|
||||
cleanText = cleanText.replace(/\s+/g, ' ').trim();
|
||||
|
||||
if (!cleanText || cleanText.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return cleanText;
|
||||
}
|
||||
|
||||
export function stripHtml(html: string): string {
|
||||
if (!html || typeof html !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = html;
|
||||
let cleanText = tempDiv.textContent || tempDiv.innerText || '';
|
||||
|
||||
cleanText = removeZalgoText(cleanText);
|
||||
|
||||
return cleanText;
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import { format } from "date-fns";
|
||||
import { AchievementNotificationInfo } from "@types";
|
||||
|
||||
export * from "./constants";
|
||||
export * from "./html-sanitizer";
|
||||
|
||||
export class UserNotLoggedInError extends Error {
|
||||
constructor() {
|
||||
|
||||
Reference in New Issue
Block a user