diff --git a/webapp/channels/src/utils/markdown/link_only_renderer.test.tsx b/webapp/channels/src/utils/markdown/link_only_renderer.test.tsx index f0ec143c31..63fa613908 100644 --- a/webapp/channels/src/utils/markdown/link_only_renderer.test.tsx +++ b/webapp/channels/src/utils/markdown/link_only_renderer.test.tsx @@ -54,7 +54,7 @@ describe('formatWithRenderer | LinkOnlyRenderer', () => { { description: 'code block: language highlighting', inputText: '```javascript\nvar s = "JavaScript syntax highlighting";\nalert(s);\n```', - outputText: 'var s = "JavaScript syntax highlighting"; alert(s);', + outputText: 'var s = "JavaScript syntax highlighting"; alert(s);', }, { description: 'blockquote:', diff --git a/webapp/channels/src/utils/markdown/remove_markdown.test.tsx b/webapp/channels/src/utils/markdown/remove_markdown.test.tsx index 9dec81d27a..e9c2b381c0 100644 --- a/webapp/channels/src/utils/markdown/remove_markdown.test.tsx +++ b/webapp/channels/src/utils/markdown/remove_markdown.test.tsx @@ -3,9 +3,11 @@ import React from 'react'; -import {stripMarkdown} from 'utils/markdown'; +import {formatWithRenderer, stripMarkdown} from 'utils/markdown'; -describe('stripMarkdown | RemoveMarkdown', () => { +import RemoveMarkdown from './remove_markdown'; + +describe('stripMarkdown', () => { const testCases = [ { description: 'emoji: same', @@ -291,7 +293,30 @@ describe('stripMarkdown | RemoveMarkdown', () => { }, ]; - testCases.forEach((testCase) => it(testCase.description, () => { + testCases.forEach((testCase) => test(testCase.description, () => { expect(stripMarkdown(testCase.inputText as any)).toEqual(testCase.outputText); })); }); + +describe('RemoveMarkdown', () => { + test('should escape HTML entities in plain text', () => { + const input = 'This looks like html: Mac & "cheese\'s"'; + const expected = 'This looks like html: <span>Mac & "cheese's"'; + + expect(formatWithRenderer(input, new RemoveMarkdown())).toBe(expected); + }); + + test('should escape HTML entities in code spans', () => { + const input = 'This looks like html: `Mac & "cheese\'s"`'; + const expected = 'This looks like html: <span>Mac & "cheese's"'; + + expect(formatWithRenderer(input, new RemoveMarkdown())).toBe(expected); + }); + + test('should escape HTML entities in code', () => { + const input = 'This looks like html:\n```\nMac & "cheese\'s"\n```'; + const expected = 'This looks like html: <span>Mac & "cheese's"'; + + expect(formatWithRenderer(input, new RemoveMarkdown())).toBe(expected); + }); +}); diff --git a/webapp/channels/src/utils/markdown/remove_markdown.ts b/webapp/channels/src/utils/markdown/remove_markdown.ts index 18e362c11f..7c1f16044d 100644 --- a/webapp/channels/src/utils/markdown/remove_markdown.ts +++ b/webapp/channels/src/utils/markdown/remove_markdown.ts @@ -3,9 +3,13 @@ import marked from 'marked'; +import * as TextFormatting from 'utils/text_formatting'; + export default class RemoveMarkdown extends marked.Renderer { public code(text: string) { - return text.replace(/\n/g, ' '); + // We need to escape the input here because our version of marked does this in the renderer. Every other node + // type has its input escaped before it reaches the renderer. + return TextFormatting.escapeHtml(text).replace(/\n/g, ' '); } public blockquote(text: string) {