From 379da42f2e5795dcd5eb63b7264678b8129d5fdf Mon Sep 17 00:00:00 2001 From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:58:57 +0200 Subject: [PATCH 1/6] add link redirection in comment textarea --- .../comment-textarea.component.html | 1 + .../comment-textarea.component.ts | 36 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.html b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.html index 178dbd06f9..8d3c65f03c 100644 --- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.html +++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.html @@ -11,6 +11,7 @@ (paste)="onPaste($event)" tabindex="0" [ngClass]="{ invalid: content.errors?.maxlength }" + (blur)="onCommentTextareaBlur()" >
{{ 'homepage.eco-news.comment.reply-error-message' | translate }}
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
index eb70b4868e..ab531c9e58 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
@@ -21,6 +21,7 @@ import { debounceTime, filter, takeUntil, tap } from 'rxjs/operators';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { CHAT_ICONS } from 'src/app/chat/chat-icons';
import { insertEmoji } from '../add-emoji/add-emoji';
+import { Patterns } from '@assets/patterns/patterns';
@Component({
selector: 'app-comment-textarea',
@@ -115,7 +116,17 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
}
private handleInputChange(): void {
- this.content.setValue(this.commentTextarea.nativeElement.textContent);
+ const textContent = this.commentTextarea.nativeElement.textContent;
+
+ if (this.content.value !== textContent) {
+ this.content.setValue(textContent);
+ }
+
+ if (Patterns.linkPattern.test(textContent)) {
+ this.commentTextarea.nativeElement.innerHTML = this.renderLinks(textContent);
+ this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
+ }
+
this.emitComment();
this.closeDropdownIfNoTag();
}
@@ -211,6 +222,13 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
selection.addRange(range);
}
+ onCommentTextareaBlur(): void {
+ const strippedText = this.commentTextarea.nativeElement.textContent;
+ this.commentTextarea.nativeElement.textContent = strippedText;
+ this.content.setValue(strippedText);
+ this.emitComment();
+ }
+
onCommentKeyDown(event: KeyboardEvent): void {
if (event.key === 'Enter' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
event.preventDefault();
@@ -267,6 +285,22 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
});
}
+ renderLinks(text: string): string {
+ return text.replace(Patterns.urlLinkifyPattern, (match) => {
+ return `${match}`;
+ });
+ }
+
+ initializeLinkClickListeners(element: HTMLElement): void {
+ const links = element.querySelectorAll('a');
+ links.forEach((link: HTMLAnchorElement) => {
+ link.addEventListener('click', (event) => {
+ event.preventDefault();
+ window.open(link.href, '_blank', 'noopener,noreferrer');
+ });
+ });
+ }
+
private insertTextAtCursor(text: string): void {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
From 26f0c86f2e18f19f0d12f07a0e7dae0cfa425c4c Mon Sep 17 00:00:00 2001
From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com>
Date: Thu, 19 Dec 2024 14:19:57 +0200
Subject: [PATCH 2/6] small fix
---
.../comment-textarea/comment-textarea.component.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
index ab531c9e58..8174f42598 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
@@ -208,8 +208,9 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
onCommentTextareaFocus(): void {
const currentText = this.commentTextarea.nativeElement.textContent.trim();
- if (currentText === 'Add a comment' || currentText === '') {
- this.commentTextarea.nativeElement.textContent = '';
+ if (Patterns.urlLinkifyPattern.test(currentText)) {
+ this.commentTextarea.nativeElement.innerHTML = this.renderLinks(currentText);
+ this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
}
const range = document.createRange();
From 2c147f390aa2e11afd1d9e1dd6e118dca2a086b4 Mon Sep 17 00:00:00 2001
From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com>
Date: Thu, 19 Dec 2024 14:35:08 +0200
Subject: [PATCH 3/6] small fix
---
.../components/comment-textarea/comment-textarea.component.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
index 8174f42598..64ce0bb4fe 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
@@ -208,6 +208,9 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
onCommentTextareaFocus(): void {
const currentText = this.commentTextarea.nativeElement.textContent.trim();
+ if (currentText === 'Add a comment' || currentText === '') {
+ this.commentTextarea.nativeElement.textContent = '';
+ }
if (Patterns.urlLinkifyPattern.test(currentText)) {
this.commentTextarea.nativeElement.innerHTML = this.renderLinks(currentText);
this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
From 4d693afc27361b1bb680bbc3bbd84ea65bd15773 Mon Sep 17 00:00:00 2001
From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com>
Date: Thu, 19 Dec 2024 14:40:17 +0200
Subject: [PATCH 4/6] remove dublications
---
.../comment-textarea.component.ts | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
index 64ce0bb4fe..451aebcdc9 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
@@ -122,10 +122,7 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
this.content.setValue(textContent);
}
- if (Patterns.linkPattern.test(textContent)) {
- this.commentTextarea.nativeElement.innerHTML = this.renderLinks(textContent);
- this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
- }
+ this.updateLinksInTextarea(textContent);
this.emitComment();
this.closeDropdownIfNoTag();
@@ -211,11 +208,8 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
if (currentText === 'Add a comment' || currentText === '') {
this.commentTextarea.nativeElement.textContent = '';
}
- if (Patterns.urlLinkifyPattern.test(currentText)) {
- this.commentTextarea.nativeElement.innerHTML = this.renderLinks(currentText);
- this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
- }
+ this.updateLinksInTextarea(currentText);
const range = document.createRange();
const nodeAmount = this.commentTextarea.nativeElement.childNodes.length;
range.setStartAfter(this.commentTextarea.nativeElement.childNodes[nodeAmount - 1]);
@@ -289,6 +283,13 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
});
}
+ private updateLinksInTextarea(currentText: string): void {
+ if (Patterns.urlLinkifyPattern.test(currentText)) {
+ this.commentTextarea.nativeElement.innerHTML = this.renderLinks(currentText);
+ this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
+ }
+ }
+
renderLinks(text: string): string {
return text.replace(Patterns.urlLinkifyPattern, (match) => {
return `${match}`;
From 6f0c7bb365afc2cc2ddf1540f80482e3b7371ee6 Mon Sep 17 00:00:00 2001
From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com>
Date: Thu, 19 Dec 2024 15:33:57 +0200
Subject: [PATCH 5/6] change according to comments
---
.../comment-textarea.component.ts | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
index 451aebcdc9..b033d7c047 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.ts
@@ -222,7 +222,6 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
onCommentTextareaBlur(): void {
const strippedText = this.commentTextarea.nativeElement.textContent;
- this.commentTextarea.nativeElement.textContent = strippedText;
this.content.setValue(strippedText);
this.emitComment();
}
@@ -285,24 +284,31 @@ export class CommentTextareaComponent implements OnInit, AfterViewInit, OnChange
private updateLinksInTextarea(currentText: string): void {
if (Patterns.urlLinkifyPattern.test(currentText)) {
- this.commentTextarea.nativeElement.innerHTML = this.renderLinks(currentText);
- this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
+ const sanitizedHtml = this.sanitizer.sanitize(SecurityContext.HTML, this.renderLinks(currentText));
+ if (sanitizedHtml) {
+ this.commentTextarea.nativeElement.innerHTML = sanitizedHtml;
+ this.initializeLinkClickListeners(this.commentTextarea.nativeElement);
+ }
}
}
renderLinks(text: string): string {
return text.replace(Patterns.urlLinkifyPattern, (match) => {
- return `${match}`;
+ const safeUrl = this.sanitizer.sanitize(SecurityContext.URL, match) || '';
+ return `${match}`;
});
}
initializeLinkClickListeners(element: HTMLElement): void {
- const links = element.querySelectorAll('a');
- links.forEach((link: HTMLAnchorElement) => {
- link.addEventListener('click', (event) => {
+ element.addEventListener('click', (event) => {
+ const target = event.target as HTMLElement;
+ if (target.tagName === 'A') {
event.preventDefault();
- window.open(link.href, '_blank', 'noopener,noreferrer');
- });
+ const href = target.getAttribute('href');
+ if (href) {
+ window.open(href, '_blank', 'noopener,noreferrer');
+ }
+ }
});
}
From 55d78ae9aaf6ea704e2ee94ba67c1894b3207ef3 Mon Sep 17 00:00:00 2001
From: Anastasia <155824290+kryzanivska-nastya@users.noreply.github.com>
Date: Fri, 20 Dec 2024 11:59:32 +0200
Subject: [PATCH 6/6] add tests
---
.../comment-textarea.component.spec.ts | 87 ++++++++++++++++++-
1 file changed, 85 insertions(+), 2 deletions(-)
diff --git a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.spec.ts b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.spec.ts
index 15db77d09f..21c67212fc 100644
--- a/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.spec.ts
+++ b/src/app/main/component/comments/components/comment-textarea/comment-textarea.component.spec.ts
@@ -5,17 +5,19 @@ import { SocketService } from '@global-service/socket/socket.service';
import { LocalStorageService } from '@global-service/localstorage/local-storage.service';
import { BehaviorSubject, Observable } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
-import { By } from '@angular/platform-browser';
+import { By, DomSanitizer } from '@angular/platform-browser';
import { PlaceholderForDivDirective } from 'src/app/main/component/comments/directives/placeholder-for-div.directive';
import { MatSelectModule } from '@angular/material/select';
import { UserProfileImageComponent } from '@global-user/components/shared/components/user-profile-image/user-profile-image.component';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { ElementRef } from '@angular/core';
describe('CommentTextareaComponent', () => {
let component: CommentTextareaComponent;
let fixture: ComponentFixture