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 = '';
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
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 = '';
- const resultString = '![image](https://example.com/image.png)';
- expect(parser.htmlToMarkdown(testString)).toBe(resultString);
- });
+ test('Image with alt attribute', () => {
+ const testString = '';
+ 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 = '';
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