diff --git a/packages/components/typography/__tests__/typography.test.tsx b/packages/components/typography/__tests__/typography.test.tsx
index f2193917de..4f1c279e74 100644
--- a/packages/components/typography/__tests__/typography.test.tsx
+++ b/packages/components/typography/__tests__/typography.test.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { render, fireEvent, vi, mockDelay } from '@test/utils';
+import { fireEvent, mockDelay, render, vi } from '@test/utils';
import { AngryIcon, SmileIcon } from 'tdesign-icons-react';
import { Typography } from '..';
@@ -17,23 +17,23 @@ describe('Typography 组件测试', () => {
mockGetCanvasContext.mockReturnValue({
font: vi.fn(),
measureText: vi.fn(),
- });
+ } as unknown as CanvasRenderingContext2D);
mockGetCanvasToDataURL.mockReturnValue('test');
});
test('title 测试', async () => {
const { container } = render(
{shortText});
- expect(container.firstChild.innerHTML).toBe(shortText);
+ expect((container.firstChild as HTMLElement).innerHTML).toBe(shortText);
});
test('paragraph 测试', async () => {
const { container } = render({shortText});
- expect(container.firstChild.innerHTML).toBe(shortText);
+ expect((container.firstChild as HTMLElement).innerHTML).toBe(shortText);
});
test('text 测试', async () => {
const { container } = render({shortText});
- expect(container.firstChild.innerHTML).toBe(shortText);
+ expect((container.firstChild as HTMLElement).innerHTML).toBe(shortText);
});
test('text code 测试', async () => {
@@ -116,4 +116,23 @@ describe('Typography 组件测试', () => {
fireEvent.click(container.querySelector('.t-button'));
expect(container.querySelector('.t-icon-smile')).toBeTruthy();
});
+
+ test('ellipsis 模式下 HTML 标签不被解析为真实元素', async () => {
+ const htmlStrings = [
+ { text: 'bold text', tag: 'b' },
+ { text: 'link', tag: 'a' },
+ { text: '', tag: 'script' },
+ ];
+
+ for (const { text, tag } of htmlStrings) {
+ const { container, unmount } = render(
+
+ {text}
+
,
+ );
+ expect(container.querySelector(tag)).toBeNull();
+ expect(container.querySelector('.t-typography-ellipsis-symbol-wrapper')).toHaveTextContent('...');
+ unmount();
+ }
+ });
});
diff --git a/packages/components/typography/ellipsis/Truncate.tsx b/packages/components/typography/ellipsis/Truncate.tsx
index e7c14df953..ab26cc1488 100644
--- a/packages/components/typography/ellipsis/Truncate.tsx
+++ b/packages/components/typography/ellipsis/Truncate.tsx
@@ -146,13 +146,23 @@ export default class Truncate extends React.Component
+ html
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+
// Shim innerText to consistently break lines at
but not at \n
innerText = (node: HTMLElement) => {
const div = document.createElement('div');
const contentKey = 'innerText' in window.HTMLElement.prototype ? 'innerText' : 'textContent';
- const content = node.innerHTML.replace(/\r\n|\r|\n/g, ' ');
- div.innerHTML = this.extractReplaceLinksKeys(content);
+ const replacedHtml = this.extractReplaceLinksKeys(node.innerHTML);
+ const escapedHtml = this.escapeHtml(replacedHtml);
+ const content = escapedHtml.replace(/\r\n|\r|\n/g, ' ');
+ div.innerHTML = content;
let text = div[contentKey];
diff --git a/packages/tdesign-react/.changelog/pr-4117.md b/packages/tdesign-react/.changelog/pr-4117.md
new file mode 100644
index 0000000000..3e4061d0fa
--- /dev/null
+++ b/packages/tdesign-react/.changelog/pr-4117.md
@@ -0,0 +1,6 @@
+---
+pr_number: 4117
+contributor: RylanBot
+---
+
+- fix(Typography): 修复开启 `ellipsis` 时,字符串被渲染为 HTML 标签的问题 @RylanBot ([#4117](https://github.com/Tencent/tdesign-react/pull/4117))