mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-16 21:06:22 +08:00
# Pull Request Template ## Description Fixes https://linear.app/chatwoot/issue/CW-6903/signature-delimiter-renders-as-h2-when-using-enter-line-before **1**. Fixes an issue where the signature delimiter `--` gets parsed as an H2 when using **Enter** (new paragraph) before or after it, causing it to render as a bold `\` in the message bubble. * Ensures `--` renders as plain text * Aligns renderer with parser behavior (both disable `lheading`) * Prevents stray `\` from appearing as heading text **2**. Also fixes a related editor issue where toggling signature **off** leaves behind a stray `\` or `-- \`. * Strips blank paragraph markers (`\`) and dangling hard breaks (`\<newline>`) from ProseMirror serializer * Applied in both `appendSignature` and `removeSignature` * Replaces `trimEnd()` with shared helpers (`trimTrailingBlanks` / `stripTrailingBlankMarkers`) ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? #### Screenshots **Before** <img width="194" height="204" alt="image" src="https://github.com/user-attachments/assets/b286ab50-7f89-4910-a552-1568902b93b3" /> **After** <img width="194" height="220" alt="image" src="https://github.com/user-attachments/assets/658cd543-bce2-46e2-a319-35e5374f1aef" /> **Editor** https://linear.app/chatwoot/issue/CW-6903/signature-delimiter-renders-as-in-h2-when-using-enter-line#comment-5814b882 ### Steps #### Editor 1. Enable agent signature 2. Add and remove new lines around the signature using Enter/shift enter 3. Toggle signature off 4. Notice stray `\` or `-- \` remains #### Bubble 1. Enable agent signature 2. Send a message using Enter between lines 3. Verify `--` renders correctly (no H2, no bold `\`) ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Muhsin Keloth <[email protected]>
140 lines
5.8 KiB
JavaScript
140 lines
5.8 KiB
JavaScript
import MessageFormatter from '../MessageFormatter';
|
|
|
|
describe('#MessageFormatter', () => {
|
|
describe('content with links', () => {
|
|
it('should format correctly', () => {
|
|
const message =
|
|
'Chatwoot is an opensource tool. [Chatwoot](https://www.chatwoot.com)';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
'<p>Chatwoot is an opensource tool. <a href="https://www.chatwoot.com" class="link" rel="noreferrer noopener nofollow" target="_blank">Chatwoot</a></p>'
|
|
);
|
|
});
|
|
it('should format correctly', () => {
|
|
const message =
|
|
'Chatwoot is an opensource tool. https://www.chatwoot.com';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
'<p>Chatwoot is an opensource tool. <a href="https://www.chatwoot.com" class="link" rel="noreferrer noopener nofollow" target="_blank">https://www.chatwoot.com</a></p>'
|
|
);
|
|
});
|
|
it('should not convert template variables to links when linkify is disabled', () => {
|
|
const message = 'Hey {{customer.name}}, check https://chatwoot.com';
|
|
const formatter = new MessageFormatter(message, false, false, false);
|
|
expect(formatter.formattedMessage).toMatch(
|
|
'<p>Hey {{customer.name}}, check https://chatwoot.com</p>'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('parses heading to strong', () => {
|
|
it('should format correctly', () => {
|
|
const message = '### opensource \n ## tool';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
`<h3>opensource</h3>
|
|
<h2>tool</h2>`
|
|
);
|
|
});
|
|
|
|
it('should not render a setext heading when text is followed by "--"', () => {
|
|
const message = 'hy\n\n\\\n\\-\\-\n\nHello there';
|
|
const result = new MessageFormatter(message).formattedMessage;
|
|
expect(result).not.toMatch('<h2>');
|
|
expect(result).not.toMatch('<h1>');
|
|
});
|
|
});
|
|
|
|
describe('content with image and has "cw_image_height" query at the end of URL', () => {
|
|
it('should set image height correctly', () => {
|
|
const message =
|
|
'Chatwoot is an opensource tool. ';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
'<p>Chatwoot is an opensource tool. <img src="http://chatwoot.com/chatwoot.png?cw_image_height=24px" alt="" style="height: 24px;" /></p>'
|
|
);
|
|
});
|
|
|
|
it('should set image height correctly if its original size', () => {
|
|
const message =
|
|
'Chatwoot is an opensource tool. ';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
'<p>Chatwoot is an opensource tool. <img src="http://chatwoot.com/chatwoot.png?cw_image_height=auto" alt="" style="height: auto;" /></p>'
|
|
);
|
|
});
|
|
|
|
it('should not set height', () => {
|
|
const message =
|
|
'Chatwoot is an opensource tool. ';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
'<p>Chatwoot is an opensource tool. <img src="http://chatwoot.com/chatwoot.png" alt="" /></p>'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('tweets', () => {
|
|
it('should return the same string if not tags or @mentions', () => {
|
|
const message = 'Chatwoot is an opensource tool';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(message);
|
|
});
|
|
|
|
it('should add links to @mentions', () => {
|
|
const message =
|
|
'@chatwootapp is an opensource tool thanks @longnonexistenttwitterusername';
|
|
expect(
|
|
new MessageFormatter(message, true, false).formattedMessage
|
|
).toMatch(
|
|
'<p><a href="http://twitter.com/chatwootapp" class="link" rel="noreferrer noopener nofollow" target="_blank">@chatwootapp</a> is an opensource tool thanks @longnonexistenttwitterusername</p>'
|
|
);
|
|
});
|
|
|
|
it('should add links to #tags', () => {
|
|
const message = '#chatwootapp is an opensource tool';
|
|
expect(
|
|
new MessageFormatter(message, true, false).formattedMessage
|
|
).toMatch(
|
|
'<p><a href="https://twitter.com/hashtag/chatwootapp" class="link" rel="noreferrer noopener nofollow" target="_blank">#chatwootapp</a> is an opensource tool</p>'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('private notes', () => {
|
|
it('should return the same string if not tags or @mentions', () => {
|
|
const message = 'Chatwoot is an opensource tool';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(message);
|
|
});
|
|
|
|
it('should add links to @mentions', () => {
|
|
const message =
|
|
'@chatwootapp is an opensource tool thanks @longnonexistenttwitterusername';
|
|
expect(
|
|
new MessageFormatter(message, false, true).formattedMessage
|
|
).toMatch(message);
|
|
});
|
|
|
|
it('should add links to #tags', () => {
|
|
const message = '#chatwootapp is an opensource tool';
|
|
expect(
|
|
new MessageFormatter(message, false, true).formattedMessage
|
|
).toMatch(message);
|
|
});
|
|
});
|
|
|
|
describe('plain text content', () => {
|
|
it('returns the plain text without HTML', () => {
|
|
const message =
|
|
'<b>Chatwoot is an opensource tool. https://www.chatwoot.com</b>';
|
|
expect(new MessageFormatter(message).plainText).toMatch(
|
|
'Chatwoot is an opensource tool. https://www.chatwoot.com'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('#sanitize', () => {
|
|
it('sanitizes markup and removes all unnecessary elements', () => {
|
|
const message =
|
|
'[xssLink](javascript:alert(document.cookie))\n[normalLink](https://google.com)**I am a bold text paragraph**';
|
|
expect(new MessageFormatter(message).formattedMessage).toMatch(
|
|
`<p>[xssLink](javascript:alert(document.cookie))<br />
|
|
<a href="https://google.com" class="link" rel="noreferrer noopener nofollow" target="_blank">normalLink</a><strong>I am a bold text paragraph</strong></p>`
|
|
);
|
|
});
|
|
});
|
|
});
|