diff --git a/__tests__/ExpensiMark-HTML-test.js b/__tests__/ExpensiMark-HTML-test.js index db8893af..519e39e5 100644 --- a/__tests__/ExpensiMark-HTML-test.js +++ b/__tests__/ExpensiMark-HTML-test.js @@ -302,14 +302,14 @@ test('Test markdown replacement for emojis with emails', () => { + '[πŸ˜„] abc@gmail.com ' + '[πŸ˜„]((abc@gmail.com)) ' + '[πŸ˜„abc@gmail.com](abc@gmail.com) ' - + '[πŸ˜„ abc@gmail.com ](abc@gmail.com) ' + + '[πŸ˜„ abc@gmail.com ](abc@gmail.com) '; const result = 'Do not replace the emoji with link ' + '[πŸ˜„](abc@gmail.com) ' + '[πŸ˜„]( abc@gmail.com) ' + '[πŸ˜„] abc@gmail.com ' + '[πŸ˜„]((abc@gmail.com)) ' + '[πŸ˜„abc@gmail.com](abc@gmail.com) ' - + '[πŸ˜„ abc@gmail.com ](abc@gmail.com) ' + + '[πŸ˜„ abc@gmail.com ](abc@gmail.com) '; expect(parser.replace(testString)).toBe(result); }); @@ -318,14 +318,14 @@ test('Test markdown replacement for composite emoji', () => { + 'πŸ˜Άβ€πŸŒ«οΈ ' + 'πŸ§‘β€πŸ”§ ' + 'πŸ‘¨β€πŸ« ' - + 'πŸ‘¨πŸΎβ€β€οΈβ€πŸ‘¨πŸ½ ' + + 'πŸ‘¨πŸΎβ€β€οΈβ€πŸ‘¨πŸ½ '; const result = 'Replace composite emoji with only one emoji tag ' + 'πŸ˜Άβ€πŸŒ«οΈ ' + 'πŸ§‘β€πŸ”§ ' + 'πŸ‘¨β€πŸ« ' - + 'πŸ‘¨πŸΎβ€β€οΈβ€πŸ‘¨πŸ½ ' + + 'πŸ‘¨πŸΎβ€β€οΈβ€πŸ‘¨πŸ½ '; expect(parser.replace(testString)).toBe(result); -}) +}); // Markdown style links replaced successfully @@ -550,30 +550,30 @@ test('Test wrapped URLs', () => { }); test('Test Url, where double quote is not allowed', () => { - const urlTestStartString = '"om https://www.she.com/"\n' + - '"om https://www.she.com"\n' + - '"https://www.she.com/ end"\n' + - '"https://www.she.com end"\n' + - 'https://www.she.com/path?test="123"\n' + - 'https://www.she.com/path?test="123/"\n' + - '"https://www.she.com/path?test="123"\n' + - '"https://www.she.com/path?test="123/"\n' + - 'https://www.she.com/path?test=123"\n' + - 'https://www.she.com/path?test=123/"\n' + - 'https://www.she.com/path?test=/"123"\n' + - 'https://www.she.com/path?test=/"123/"'; - const urlTestReplacedString = '"om https://www.she.com/"
' + - '"om https://www.she.com"
' + - '"https://www.she.com/ end"
' + - '"https://www.she.com end"
' + - 'https://www.she.com/path?test="123"
' + - 'https://www.she.com/path?test="123/"
' + - '"https://www.she.com/path?test="123"
' + - '"https://www.she.com/path?test="123/"
' + - 'https://www.she.com/path?test=123"
' + - 'https://www.she.com/path?test=123/"
' + - 'https://www.she.com/path?test=/"123"
' + - 'https://www.she.com/path?test=/"123/"'; + const urlTestStartString = '"om https://www.she.com/"\n' + + '"om https://www.she.com"\n' + + '"https://www.she.com/ end"\n' + + '"https://www.she.com end"\n' + + 'https://www.she.com/path?test="123"\n' + + 'https://www.she.com/path?test="123/"\n' + + '"https://www.she.com/path?test="123"\n' + + '"https://www.she.com/path?test="123/"\n' + + 'https://www.she.com/path?test=123"\n' + + 'https://www.she.com/path?test=123/"\n' + + 'https://www.she.com/path?test=/"123"\n' + + 'https://www.she.com/path?test=/"123/"'; + const urlTestReplacedString = '"om https://www.she.com/"
' + + '"om https://www.she.com"
' + + '"https://www.she.com/ end"
' + + '"https://www.she.com end"
' + + 'https://www.she.com/path?test="123"
' + + 'https://www.she.com/path?test="123/"
' + + '"https://www.she.com/path?test="123"
' + + '"https://www.she.com/path?test="123/"
' + + 'https://www.she.com/path?test=123"
' + + 'https://www.she.com/path?test=123/"
' + + 'https://www.she.com/path?test=/"123"
' + + 'https://www.she.com/path?test=/"123/"'; expect(parser.replace(urlTestStartString)).toBe(urlTestReplacedString); }); @@ -732,7 +732,7 @@ test('Test urls with unmatched closing parentheses autolinks correctly', () => { resultString: 'google.com/(toto))titi)', }, ]; - testCases.forEach(testCase => { + testCases.forEach((testCase) => { expect(parser.replace(testCase.testString)).toBe(testCase.resultString); }); }); @@ -867,7 +867,7 @@ test('Test urls autolinks correctly', () => { }, ]; - testCases.forEach(testCase => { + testCases.forEach((testCase) => { expect(parser.replace(testCase.testString)).toBe(testCase.resultString); }); }); @@ -1137,7 +1137,7 @@ test('Test for link with no content', () => { test('Test for link with emoji', () => { const testString = '[πŸ˜€](www.link.com)'; - const resultString = '[πŸ˜€](www.link.com)';; + const resultString = '[πŸ˜€](www.link.com)'; expect(parser.replace(testString)).toBe(resultString); }); test('Test quotes markdown replacement with heading inside', () => { @@ -1472,7 +1472,7 @@ test('Test for mention inside link and email markdown', () => { expect(parser.replace(testString)).toBe(resultString); }); -test('Skip rendering invalid markdown',() => { +test('Skip rendering invalid markdown', () => { let testString = '_*test_*'; expect(parser.replace(testString)).toBe('*test*'); @@ -1959,5 +1959,116 @@ describe('Image markdown conversion to html tag', () => { const testString = '![`code`](https://example.com/image.png)'; const resultString = '<code>code</code>'; expect(parser.replace(testString)).toBe(resultString); - }) + }); +}); + +describe('room mentions', () => { + test('simple room mention', () => { + const testString = '#room'; + const resultString = '#room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with leading word and space', () => { + const testString = 'hi all #room'; + const resultString = 'hi all #room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with leading word and no space', () => { + const testString = 'hi all#room'; + const resultString = 'hi all#room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with space between hash and room name', () => { + const testString = '# room'; + const resultString = '

room

'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with markdown syntax before the # prefix', () => { + const testString = 'hello *#room'; + const resultString = 'hello *#room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with italic, bold and strikethrough styles', () => { + const testString = '#room' + + ' _#room_' + + ' *#room*' + + ' ~#room~' + + ' [#room](google.com)' + + ' #room abc' + + ' #room*' + + ' #room~' + + ' #room#' + + ' #room@' + + ' #room$' + + ' #room^' + + ' #room(' + + ' #room.' + + ' #room!' + + ' #room?'; + + const resultString = '#room' + + ' #room' + + ' #room' + + ' #room' + + ' #room' + + ' #room abc' + + ' #room*' + + ' #room~' + + ' #room#' + + ' #room@' + + ' #room$' + + ' #room^' + + ' #room(' + + ' #room.' + + ' #room!' + + ' #room?'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention inside link should not be rendered', () => { + const testString = '[#room](google.com)'; + const resultString = '#room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with space inside link should not be rendered', () => { + const testString = '[ #room](google.com/sub#111)'; + const resultString = '#room'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention inside code block should not be rendered', () => { + const testString = '```\n#room\n```'; + const resultString = '
#room
'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention without room name', () => { + const testString = '#'; + const resultString = '#'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with numbers', () => { + const testString = '#room123'; + const resultString = '#room123'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with hyphens', () => { + const testString = '#room-name'; + const resultString = '#room-name'; + expect(parser.replace(testString)).toBe(resultString); + }); + + test('room mention with hypens and numbers', () => { + const testString = '#room-name123'; + const resultString = '#room-name123'; + expect(parser.replace(testString)).toBe(resultString); + }); }); diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index ada9fd90..e8e27d90 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -529,7 +529,7 @@ test('Test heading1 markdown replacement when # is followed by multiple spaces', test('Test heading1 markdown when # is not followed by a space', () => { const testString = '#This is not a heading1 because starts with a # but has no space after it\n'; - const resultString = '#This is not a heading1 because starts with a # but has no space after it
'; + const resultString = '#This is not a heading1 because starts with a # but has no space after it
'; expect(parser.replace(testString)).toBe(resultString); }); @@ -688,7 +688,7 @@ test('Test codeFence copy from selection does not add extra new line', () => { expect(parser.htmlToMarkdown(testString)).toBe('```\ncode\n```\ntext'); testString = '

test heading

Code snippet\n

link

'; - expect(parser.htmlToMarkdown(testString)).toBe('test heading\n```\nCode snippet\n```\n> [link](https://www.example.com)') + expect(parser.htmlToMarkdown(testString)).toBe('test heading\n```\nCode snippet\n```\n> [link](https://www.example.com)'); }); test('Linebreak should be remained for text between code block', () => { @@ -758,17 +758,17 @@ test('Mention html to markdown', () => { }); describe('Image tag conversion to markdown', () => { - test('Image with alt attribute', () => { - const testString = 'image'; - const resultString = '![image](https://example.com/image.png)'; - expect(parser.htmlToMarkdown(testString)).toBe(resultString); - }); + test('Image with alt attribute', () => { + const testString = 'image'; + const resultString = '![image](https://example.com/image.png)'; + expect(parser.htmlToMarkdown(testString)).toBe(resultString); + }); - test('Image without alt attribute', () => { + test('Image without alt attribute', () => { const testString = ''; const resultString = '![https://example.com/image.png](https://example.com/image.png)'; expect(parser.htmlToMarkdown(testString)).toBe(resultString); - }); + }); test('Image with alt text containing escaped markdown', () => { const testString = '*bold* _italic_ ~strike~'; diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index e3822d20..7d5be4e2 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -169,6 +169,19 @@ export default class ExpensiMark { }, }, + /** + * A room mention is a string that starts with the '#' symbol and is followed by a valid room name. + * + * Note: We are allowing mentions in a format of #room-name The room name can contain any + * combination of letters and hyphens + */ + { + name: 'roomMentions', + + regex: /(?$1', + }, + /** * This regex matches a valid user mention in a string. * A user mention is a string that starts with the '@' symbol and is followed by a valid user's primary