mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-21 01:53:57 +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 { ReviewSortOptions } from "./review-sort-options";
|
||||||
import { ReviewPromptBanner } from "./review-prompt-banner";
|
import { ReviewPromptBanner } from "./review-prompt-banner";
|
||||||
|
|
||||||
|
import { sanitizeHtml } from "@shared";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { cloudSyncContext, gameDetailsContext } from "@renderer/context";
|
import { cloudSyncContext, gameDetailsContext } from "@renderer/context";
|
||||||
import { AuthPage } from "@shared";
|
import { AuthPage } from "@shared";
|
||||||
@@ -123,7 +124,12 @@ export function GameDetailsContent() {
|
|||||||
|
|
||||||
// Tiptap editor for review input
|
// Tiptap editor for review input
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
extensions: [StarterKit],
|
extensions: [
|
||||||
|
StarterKit.configure({
|
||||||
|
// Disable link extension to prevent automatic link rendering and XSS
|
||||||
|
link: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
content: "",
|
content: "",
|
||||||
editorProps: {
|
editorProps: {
|
||||||
attributes: {
|
attributes: {
|
||||||
@@ -739,7 +745,7 @@ export function GameDetailsContent() {
|
|||||||
<div
|
<div
|
||||||
className="game-details__review-content"
|
className="game-details__review-content"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: review.reviewHtml,
|
__html: sanitizeHtml(review.reviewHtml),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="game-details__review-actions">
|
<div className="game-details__review-actions">
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ $hero-height: 300px;
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: calc(globals.$spacing-unit * 2);
|
padding: calc(globals.$spacing-unit * 2);
|
||||||
margin-bottom: calc(globals.$spacing-unit * 2);
|
margin-bottom: calc(globals.$spacing-unit * 2);
|
||||||
|
overflow: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__review-header {
|
&__review-header {
|
||||||
@@ -233,6 +235,7 @@ $hero-height: 300px;
|
|||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
font-size: globals.$small-font-size;
|
font-size: globals.$small-font-size;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
&--clickable {
|
&--clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -383,6 +386,11 @@ $hero-height: 300px;
|
|||||||
&__review-content {
|
&__review-content {
|
||||||
color: globals.$body-color;
|
color: globals.$body-color;
|
||||||
line-height: 1.5;
|
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 {
|
&__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";
|
import { AchievementNotificationInfo } from "@types";
|
||||||
|
|
||||||
export * from "./constants";
|
export * from "./constants";
|
||||||
|
export * from "./html-sanitizer";
|
||||||
|
|
||||||
export class UserNotLoggedInError extends Error {
|
export class UserNotLoggedInError extends Error {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
Reference in New Issue
Block a user