Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into multiple-quote
Browse files Browse the repository at this point in the history
  • Loading branch information
robertKozik committed Feb 24, 2024
2 parents 00c2a19 + e4c35b7 commit 711610b
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 22 deletions.
32 changes: 23 additions & 9 deletions __tests__/ExpensiMark-HTML-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,29 @@ test('Test markdown replacement for emojis with emails', () => {
+ '[😄abc@gmail.com](abc@gmail.com) '
+ '[😄 abc@gmail.com ](abc@gmail.com) '
const result = 'Do not replace the emoji with link '
+ '[😄](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[😄]( <a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[😄] <a href="mailto:abc@gmail.com">abc@gmail.com</a> '
+ '[😄]((<a href="mailto:abc@gmail.com">abc@gmail.com</a>)) '
+ '[😄<a href="mailto:abc@gmail.com">abc@gmail.com</a>](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[😄 <a href="mailto:abc@gmail.com">abc@gmail.com</a> ](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[<emoji>😄</emoji>](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[<emoji>😄</emoji>]( <a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[<emoji>😄</emoji>] <a href="mailto:abc@gmail.com">abc@gmail.com</a> '
+ '[<emoji>😄</emoji>]((<a href="mailto:abc@gmail.com">abc@gmail.com</a>)) '
+ '[<emoji>😄</emoji><a href="mailto:abc@gmail.com">abc@gmail.com</a>](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
+ '[<emoji>😄</emoji> <a href="mailto:abc@gmail.com">abc@gmail.com</a> ](<a href="mailto:abc@gmail.com">abc@gmail.com</a>) '
expect(parser.replace(testString)).toBe(result);
});

test('Test markdown replacement for composite emoji', () => {
const testString = 'Replace composite emoji with only one emoji tag '
+ '😶‍🌫️ '
+ '🧑‍🔧 '
+ '👨‍🏫 '
+ '👨🏾‍❤️‍👨🏽 '
const result = 'Replace composite emoji with only one emoji tag '
+ '<emoji>😶‍🌫️</emoji> '
+ '<emoji>🧑‍🔧</emoji> '
+ '<emoji>👨‍🏫</emoji> '
+ '<emoji>👨🏾‍❤️‍👨🏽</emoji> '
expect(parser.replace(testString)).toBe(result);
})


// Markdown style links replaced successfully
test('Test markdown style links', () => {
Expand Down Expand Up @@ -1107,7 +1121,7 @@ test('Test for link with no content', () => {

test('Test for link with emoji', () => {
const testString = '[😀](www.link.com)';
const resultString = '[😀](<a href="https://www.link.com" target="_blank" rel="noreferrer noopener">www.link.com</a>)';
const resultString = '[<emoji>😀</emoji>](<a href="https://www.link.com" target="_blank" rel="noreferrer noopener">www.link.com</a>)';
expect(parser.replace(testString)).toBe(resultString);
});
test('Test quotes markdown replacement with heading inside', () => {
Expand Down Expand Up @@ -1150,8 +1164,8 @@ test('Test for user mention with @@username@domain.com', () => {
expect(parser.replace(testString)).toBe(resultString);
});

test('Test for user mention with @phoneNumber@domain.sms', () => {
const testString = '@+19728974297@expensify.sms';
test('Test for user mention with @phoneNumber', () => {
const testString = '@+19728974297';
const resultString = '<mention-user>@+19728974297@expensify.sms</mention-user>';
expect(parser.replace(testString)).toBe(resultString);
});
Expand Down
4 changes: 2 additions & 2 deletions __tests__/ExpensiMark-Markdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ test('Test multi-line italic HTML replacement', () => {
expect(parser.htmlToMarkdown(testString)).toBe(replacedString);
});

// Words wrapped in ~ successfully replaced with <del></del>
// Words wrapped in <del></del> or <s></s> successfully replaced with ~
test('Test strikethrough HTML replacement', () => {
const strikethroughTestStartString = 'This is a <del>sentence,</del> and it has some <del>punctuation, words, and spaces</del>. <del>test</del> ~ testing~ test~test~test. ~ testing ~ ~testing ~';
const strikethroughTestStartString = 'This is a <del>sentence,</del> and it has some <del>punctuation, words, and spaces</del>. <s>test</s> ~ testing~ test~test~test. ~ testing ~ ~testing ~';
const strikethroughTestReplacedString = 'This is a ~sentence,~ and it has some ~punctuation, words, and spaces~. ~test~ ~ testing~ test~test~test. ~ testing ~ ~testing ~';
expect(parser.htmlToMarkdown(strikethroughTestStartString)).toBe(strikethroughTestReplacedString);
});
Expand Down
10 changes: 10 additions & 0 deletions lib/CONST.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ export declare const CONST: {
* Regex matching an text containing an email
*/
readonly EMAIL_PART: "([\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*@(?:[\\w\\-]+\\.)+[a-z]{2,})";
/**
* Regex matching a text containing an E.164 format phone number
*/
readonly PHONE_PART: "\\+[1-9]\\d{1,14}";
/**
* Regular expression to check that a basic name is valid
*/
Expand Down Expand Up @@ -285,6 +289,12 @@ export declare const CONST: {
* Regex matching an text containing an Emoji
*/
readonly EMOJIS: RegExp;
/**
* Regex matching an text containing an Emoji that can be a single emoji or made up by some different emojis
*
* @type RegExp
*/
readonly EMOJI_RULE: RegExp;
};
readonly REPORT: {
/**
Expand Down
14 changes: 13 additions & 1 deletion lib/CONST.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ export const CONST = {
*/
EMAIL_PART: EMAIL_BASE_REGEX,

/**
* Regex matching a text containing an E.164 format phone number
*/
PHONE_PART: '\\+[1-9]\\d{1,14}',

/**
* Regular expression to check that a basic name is valid
*
Expand Down Expand Up @@ -352,6 +357,13 @@ export const CONST = {
* @type RegExp
*/
EMOJIS: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu,

/**
* Regex matching an text containing an Emoji that can be a single emoji or made up by some different emojis
*
* @type RegExp
*/
EMOJI_RULE: /[\p{Extended_Pictographic}](\u200D[\p{Extended_Pictographic}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/gu,
},

REPORT: {
Expand Down Expand Up @@ -556,7 +568,7 @@ export const CONST = {
// Domain used for accounts that sign up with phone numbers
DOMAIN: 'expensify.sms',

// Regex that matches on a E.164 phone number starting with a '+'
// Regex that matches on an E.164 phone number starting with a '+'
E164_REGEX: /^\+?[1-9]\d{1,14}$/,
},

Expand Down
18 changes: 13 additions & 5 deletions lib/ExpensiMark.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ export default class ExpensiMark {
* @type {Object[]}
*/
this.rules = [
// Apply the emoji first avoid applying any other formatting rules inside of it
{
name: 'emoji',
regex: CONST.REG_EXP.EMOJI_RULE,
replacement: match => `<emoji>${match}</emoji>`
},

/**
* Apply the code-fence first so that we avoid replacing anything inside of it that we're not supposed to
* Apply the code-fence to avoid replacing anything inside of it that we're not supposed to
* (aka any rule with the '(?![^<]*<\/pre>)' avoidance in it
*/
{
Expand Down Expand Up @@ -151,17 +158,18 @@ export default class ExpensiMark {
* 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 login
*
* Note: currently we are only allowing mentions in a format of @+19728974297@expensify.sms and @username@example.com
* Note: currently we are only allowing mentions in a format of @+19728974297 (E.164 format phone number) and @username@example.com
* The username can contain any combination of alphanumeric letters, numbers, and underscores
*/
{
name: 'userMentions',
regex: new RegExp(`(@here|[a-zA-Z0-9.!$%&+=?^\`{|}-]?)(@${CONST.REG_EXP.EMAIL_PART})(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>))`, 'gim'),
regex: new RegExp(`(@here|[a-zA-Z0-9.!$%&+=?^\`{|}-]?)(@${CONST.REG_EXP.EMAIL_PART}|@${CONST.REG_EXP.PHONE_PART})(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>))`, 'gim'),
replacement: (match, g1, g2) => {
if (!Str.isValidMention(match)) {
return match;
}
return `${g1}<mention-user>${g2}</mention-user>`;
const phoneRegex = new RegExp(`^@${CONST.REG_EXP.PHONE_PART}$`);
return `${g1}<mention-user>${g2}${phoneRegex.test(g2) ? `@${CONST.SMS.DOMAIN}` : ''}</mention-user>`;
},
},

Expand Down Expand Up @@ -373,7 +381,7 @@ export default class ExpensiMark {
},
{
name: 'strikethrough',
regex: /<(del)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi,
regex: /<(del|s)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi,
replacement: '~$2~',
},
{
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"url": "git+ssh://git@github.com/Expensify/JS-Libs.git"
},
"dependencies": {
"classnames": "2.4.0",
"classnames": "2.5.0",
"clipboard": "2.0.11",
"html-entities": "^2.4.0",
"jquery": "3.6.0",
Expand Down

0 comments on commit 711610b

Please sign in to comment.