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))