expensify-common
Advanced tools
Comparing version 1.0.0 to 1.0.1
/* eslint-disable max-len */ | ||
import ExpensiMark from '../lib/ExpensiMark'; | ||
const parser = new ExpensiMark(); | ||
@@ -15,2 +16,10 @@ | ||
// Words wrapped in * successfully replaced with <strong></strong> | ||
test('Test quote markdown replacement', () => { | ||
const quoteTestStartString = '>This is a *quote* that started on a new line.\nHere is a >quote that did not\n```\nhere is a codefenced quote\n>it should not be quoted\n```'; | ||
const quoteTestReplacedString = '<blockquote>This is a <strong>quote</strong> that started on a new line.</blockquote>Here is a >quote that did not<br><pre>here is a codefenced quote<br>>it should not be quoted</pre>'; | ||
expect(parser.replace(quoteTestStartString)).toBe(quoteTestReplacedString); | ||
}); | ||
// Words wrapped in _ successfully replaced with <em></em> | ||
@@ -32,7 +41,36 @@ test('Test italic markdown replacement', () => { | ||
test('Test markdown style links', () => { | ||
const testString = 'Go to [Expensify](https://www.expensify.com) to learn more. [Expensify](www.expensify.com) [Expensify](expensify.com)'; | ||
const resultString = 'Go to <a href="https://www.expensify.com" target="_blank">Expensify</a> to learn more. <a href="http://www.expensify.com" target="_blank">Expensify</a> <a href="http://expensify.com" target="_blank">Expensify</a>'; | ||
const testString = 'Go to [Expensify](https://www.expensify.com) to learn more. [Expensify](www.expensify.com) [Expensify](expensify.com) [It\'s really the coolest](expensify.com) [`Some` Special cases - + . = , \'](expensify.com/some?query=par|am)'; | ||
const resultString = 'Go to <a href="https://www.expensify.com" target="_blank">Expensify</a> to learn more. <a href="http://www.expensify.com" target="_blank">Expensify</a> <a href="http://expensify.com" target="_blank">Expensify</a> <a href="http://expensify.com" target="_blank">It's really the coolest</a> <a href="http://expensify.com/some?query=par|am" target="_blank"><code>Some</code> Special cases - + . = , '</a>'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
// Critical Markdown style links replaced successfully | ||
test('Test critical markdown style links', () => { | ||
const testString = 'Testing ' | ||
+ '[first](https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878) ' | ||
+ '[first no https://](www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878) ' | ||
+ '[second](http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled) ' | ||
+ '[second no http://](necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled) ' | ||
+ '[third](https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash) ' | ||
+ '[third no https://](github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash) ' | ||
+ '[link `[inside another link](https://google.com)`](https://google.com) ' | ||
+ '[link with an @ in it](https://google.com) ' | ||
+ '[link with [brackets] inside of it](https://google.com) ' | ||
+ '[link with smart quotes ‘’“”](https://google.com) ' | ||
+ '[link with someone@expensify.com email in it](https://google.com)'; | ||
const resultString = 'Testing ' | ||
+ '<a href="https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878" target="_blank">first</a> ' | ||
+ '<a href="http://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878" target="_blank">first no https://</a> ' | ||
+ '<a href="http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled" target="_blank">second</a> ' | ||
+ '<a href="http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled" target="_blank">second no http://</a> ' | ||
+ '<a href="https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash" target="_blank">third</a> ' | ||
+ '<a href="http://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash" target="_blank">third no https://</a> ' | ||
+ '<a href="https://google.com" target="_blank">link <code>[inside another link](https://google.com)</code></a> ' | ||
+ '<a href="https://google.com" target="_blank">link with an @ in it</a> ' | ||
+ '<a href="https://google.com" target="_blank">link with [brackets] inside of it</a> ' | ||
+ '<a href="https://google.com" target="_blank">link with smart quotes ‘’“”</a> ' | ||
+ '<a href="https://google.com" target="_blank">link with someone@expensify.com email in it</a>'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
// HTML encoded strings unaffected by parser | ||
@@ -59,9 +97,27 @@ test('Test HTML encoded strings', () => { | ||
test('Test code fencing', () => { | ||
const codeFenceExampleMarkdown = '```\nconst javaScript = \'javaScript\'\n```'; | ||
expect(parser.replace(codeFenceExampleMarkdown)).toBe('<pre>const javaScript = 'javaScript'</pre>'); | ||
let codeFenceExampleMarkdown = '```\nconst javaScript = \'javaScript\'\n```'; | ||
expect(parser.replace(codeFenceExampleMarkdown)).toBe('<pre>const javaScript = 'javaScript'</pre>'); | ||
codeFenceExampleMarkdown = '```const javaScript = \'javaScript\'\n```'; | ||
expect(parser.replace(codeFenceExampleMarkdown)).toBe('<pre>const javaScript = 'javaScript'</pre>'); | ||
codeFenceExampleMarkdown = '```\nconst javaScript = \'javaScript\'```'; | ||
expect(parser.replace(codeFenceExampleMarkdown)).toBe('<pre>const javaScript = 'javaScript'</pre>'); | ||
codeFenceExampleMarkdown = '```const javaScript = \'javaScript\'```'; | ||
expect(parser.replace(codeFenceExampleMarkdown)).toBe('<pre>const javaScript = 'javaScript'</pre>'); | ||
}); | ||
test('Test code fencing with spaces and new lines', () => { | ||
const codeFenceExample = '```\nconst javaScript = \'javaScript\'\n const php = \'php\'\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>const javaScript = 'javaScript'<br> const php = 'php'</pre>'); | ||
let codeFenceExample = '```\nconst javaScript = \'javaScript\'\n const php = \'php\'\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>const javaScript = 'javaScript'<br>    const php = 'php'</pre>'); | ||
codeFenceExample = '```const javaScript = \'javaScript\'\n const php = \'php\'\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>const javaScript = 'javaScript'<br>    const php = 'php'</pre>'); | ||
codeFenceExample = '```\nconst javaScript = \'javaScript\'\n const php = \'php\'```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>const javaScript = 'javaScript'<br>    const php = 'php'</pre>'); | ||
codeFenceExample = '```const javaScript = \'javaScript\'\n const php = \'php\'```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>const javaScript = 'javaScript'<br>    const php = 'php'</pre>'); | ||
}); | ||
@@ -79,5 +135,24 @@ | ||
test('Test inline code blocks inside ExpensiMark', () => { | ||
const testString = '_`test`_' | ||
+ '*`test`*' | ||
+ '~`test`~'; | ||
const resultString = '<em><code>test</code></em>' | ||
+ '<strong><code>test</code></strong>' | ||
+ '<del><code>test</code></del>'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test code fencing with ExpensiMark syntax inside', () => { | ||
const codeFenceExample = '```\nThis is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)</pre>'); | ||
let codeFenceExample = '```\nThis is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)</pre>'); | ||
codeFenceExample = '```This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)\n```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)</pre>'); | ||
codeFenceExample = '```\nThis is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)</pre>'); | ||
codeFenceExample = '```This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)```'; | ||
expect(parser.replace(codeFenceExample)).toBe('<pre>This is how you can write ~strikethrough~, *bold*, _italics_, and [links](https://www.expensify.com)</pre>'); | ||
}); | ||
@@ -101,20 +176,60 @@ | ||
const urlTestStartString = 'Testing ' | ||
+ 'test.com ' | ||
+ 'test again ' | ||
+ 'http://test.com/test ' | ||
+ 'www.test.com ' | ||
+ 'http://test.com) ' | ||
+ 'test.totallyfaketld ' | ||
+ 'idrink.beer ' | ||
+ 'mm..food'; | ||
+ 'foo.com ' | ||
+ 'www.foo.com ' | ||
+ 'http://www.foo.com ' | ||
+ 'http://foo.com/blah_blah ' | ||
+ 'http://foo.com/blah_blah/ ' | ||
+ 'http://foo.com/blah_blah_(wikipedia) ' | ||
+ 'http://www.example.com/wpstyle/?p=364 ' | ||
+ 'https://www.example.com/foo/?bar=baz&inga=42&quux ' | ||
+ 'http://foo.com/(something)?after=parens ' | ||
+ 'http://code.google.com/events/#&product=browser ' | ||
+ 'http://foo.bar/?q=Test%20URL-encoded%20stuff ' | ||
+ 'http://www.test.com/path?param=123#123 ' | ||
+ 'http://1337.net ' | ||
+ 'http://a.b-c.de/ ' | ||
+ 'https://sd1.sd2.docs.google.com/ ' | ||
+ 'https://expensify.cash/#/r/1234 ' | ||
+ 'https://github.com/Expensify/ReactNativeChat/pull/6.45 ' | ||
+ 'https://github.com/Expensify/Expensify/issues/143,231 ' | ||
+ 'testRareTLDs.beer ' | ||
+ 'test@expensify.com ' | ||
+ 'test.completelyFakeTLD ' | ||
+ 'https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878) ' | ||
+ 'http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled ' | ||
+ 'https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash ' | ||
+ 'https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash ' | ||
+ 'mm..food ' | ||
+ 'upwork.com/jobs/~016781e062ce860b84 ' | ||
+ 'https://bastion1.sjc/logs/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:\'2125cbe0-28a9-11e9-a79c-3de0157ed580\',interval:auto,query:(language:lucene,query:\'\'),sort:!(timestamp,desc))'; | ||
const urlTestReplacedString = 'Testing ' | ||
+ '<a href="http://test.com" target="_blank">test.com</a> ' | ||
+ 'test again ' | ||
+ '<a href="http://test.com/test" target="_blank">http://test.com/test</a> ' | ||
+ '<a href="http://www.test.com" target="_blank">www.test.com</a> ' | ||
+ '<a href="http://test.com" target="_blank">http://test.com</a>) ' | ||
+ 'test.totallyfaketld ' | ||
+ '<a href="http://idrink.beer" target="_blank">idrink.beer</a> ' | ||
+ 'mm..food'; | ||
+ '<a href="http://foo.com" target="_blank">foo.com</a> ' | ||
+ '<a href="http://www.foo.com" target="_blank">www.foo.com</a> ' | ||
+ '<a href="http://www.foo.com" target="_blank">http://www.foo.com</a> ' | ||
+ '<a href="http://foo.com/blah_blah" target="_blank">http://foo.com/blah_blah</a> ' | ||
+ '<a href="http://foo.com/blah_blah/" target="_blank">http://foo.com/blah_blah/</a> ' | ||
+ '<a href="http://foo.com/blah_blah_(wikipedia)" target="_blank">http://foo.com/blah_blah_(wikipedia)</a> ' | ||
+ '<a href="http://www.example.com/wpstyle/?p=364" target="_blank">http://www.example.com/wpstyle/?p=364</a> ' | ||
+ '<a href="https://www.example.com/foo/?bar=baz&inga=42&quux" target="_blank">https://www.example.com/foo/?bar=baz&inga=42&quux</a> ' | ||
+ '<a href="http://foo.com/(something)?after=parens" target="_blank">http://foo.com/(something)?after=parens</a> ' | ||
+ '<a href="http://code.google.com/events/#&product=browser" target="_blank">http://code.google.com/events/#&product=browser</a> ' | ||
+ '<a href="http://foo.bar/?q=Test%20URL-encoded%20stuff" target="_blank">http://foo.bar/?q=Test%20URL-encoded%20stuff</a> ' | ||
+ '<a href="http://www.test.com/path?param=123#123" target="_blank">http://www.test.com/path?param=123#123</a> ' | ||
+ '<a href="http://1337.net" target="_blank">http://1337.net</a> ' | ||
+ '<a href="http://a.b-c.de/" target="_blank">http://a.b-c.de/</a> ' | ||
+ '<a href="https://sd1.sd2.docs.google.com/" target="_blank">https://sd1.sd2.docs.google.com/</a> ' | ||
+ '<a href="https://expensify.cash/#/r/1234" target="_blank">https://expensify.cash/#/r/1234</a> ' | ||
+ '<a href="https://github.com/Expensify/ReactNativeChat/pull/6.45" target="_blank">https://github.com/Expensify/ReactNativeChat/pull/6.45</a> ' | ||
+ '<a href="https://github.com/Expensify/Expensify/issues/143,231" target="_blank">https://github.com/Expensify/Expensify/issues/143,231</a> ' | ||
+ '<a href="http://testRareTLDs.beer" target="_blank">testRareTLDs.beer</a> ' | ||
+ '<a href="mailto:test@expensify.com">test@expensify.com</a> ' | ||
+ 'test.completelyFakeTLD ' | ||
+ '<a href="https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878" target="_blank">https://www.expensify.com/_devportal/tools/logSearch/#query=request_id:(%22Ufjjim%22)+AND+timestamp:[2021-01-08T03:48:10.389Z+TO+2021-01-08T05:48:10.389Z]&index=logs_expensify-008878</a>) ' | ||
+ '<a href="http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled" target="_blank">http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled</a> ' | ||
+ '<a href="https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash" target="_blank">https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash</a> ' | ||
+ '<a href="https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash" target="_blank">https://github.com/Expensify/Expensify.cash/issues/123#:~:text=Please%20work/Expensify.cash</a> ' | ||
+ 'mm..food ' | ||
+ '<a href="http://upwork.com/jobs/~016781e062ce860b84" target="_blank">upwork.com/jobs/~016781e062ce860b84</a> ' | ||
+ '<a href="https://bastion1.sjc/logs/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'2125cbe0-28a9-11e9-a79c-3de0157ed580',interval:auto,query:(language:lucene,query:''),sort:!(timestamp,desc))" target="_blank">https://bastion1.sjc/logs/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'2125cbe0-28a9-11e9-a79c-3de0157ed580',interval:auto,query:(language:lucene,query:''),sort:!(timestamp,desc))</a>'; | ||
@@ -124,8 +239,2 @@ expect(parser.replace(urlTestStartString)).toBe(urlTestReplacedString); | ||
test('Auto-link works on a www. test url', () => { | ||
const testString = 'https://www.test.com'; | ||
const resultString = '<a href="https://www.test.com" target="_blank">https://www.test.com</a>'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test markdown style link with various styles', () => { | ||
@@ -161,8 +270,2 @@ const testString = 'Go to ~[Expensify](https://www.expensify.com)~ ' | ||
test('Test links that have a comma in the middle autolink correctly', () => { | ||
const testString = 'https://github.com/Expensify/Expensify/issues/143,231'; | ||
const resultString = '<a href="https://github.com/Expensify/Expensify/issues/143,231" target="_blank">https://github.com/Expensify/Expensify/issues/143,231</a>'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test links inside two backticks are not autolinked', () => { | ||
@@ -180,12 +283,66 @@ const testString = '`https://github.com/Expensify/Expensify/issues/143231`'; | ||
test('Test a period in the middle of a link autolinks correctly', () => { | ||
const testString = 'https://github.com/Expensify/ReactNativeChat/pull/6.45'; | ||
const resultString = '<a href="https://github.com/Expensify/ReactNativeChat/pull/6.45" target="_blank">https://github.com/Expensify/ReactNativeChat/pull/6.45</a>'; | ||
test('Test a url ending with a question mark autolinks correctly', () => { | ||
const testString = 'https://github.com/Expensify/ReactNativeChat/pull/645?'; | ||
const resultString = '<a href="https://github.com/Expensify/ReactNativeChat/pull/645" target="_blank">https://github.com/Expensify/ReactNativeChat/pull/645</a>?'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test a url with potentially valid TLD before the actual TLD autolinks correctly', () => { | ||
const testString = 'https://sd1.sd2.docs.google.com/'; | ||
const resultString = '<a href="https://sd1.sd2.docs.google.com/" target="_blank">https://sd1.sd2.docs.google.com/</a>'; | ||
test('Test a url ending with a closing parentheses autolinks correctly', () => { | ||
const testString = 'https://github.com/Expensify/ReactNativeChat/pull/645)'; | ||
const resultString = '<a href="https://github.com/Expensify/ReactNativeChat/pull/645" target="_blank">https://github.com/Expensify/ReactNativeChat/pull/645</a>)'; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test markdown style email link with various styles', () => { | ||
const testString = 'Go to ~[Expensify](concierge@expensify.com)~ ' | ||
+ '_[Expensify](concierge@expensify.com)_ ' | ||
+ '*[Expensify](concierge@expensify.com)* ' | ||
+ '[Expensify!](no-concierge1@expensify.com) ' | ||
+ '[Expensify?](concierge?@expensify.com) '; | ||
const resultString = 'Go to <del><a href="mailto:concierge@expensify.com">Expensify</a></del> ' | ||
+ '<em><a href="mailto:concierge@expensify.com">Expensify</a></em> ' | ||
+ '<strong><a href="mailto:concierge@expensify.com">Expensify</a></strong> ' | ||
+ '<a href="mailto:no-concierge1@expensify.com">Expensify!</a> ' | ||
+ '<a href="mailto:concierge?@expensify.com">Expensify?</a> '; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test general email link with various styles', () => { | ||
const testString = 'Go to concierge@expensify.com ' | ||
+ 'no-concierge@expensify.com ' | ||
+ 'concierge!@expensify.com ' | ||
+ 'concierge1?@expensify.com '; | ||
const resultString = 'Go to <a href="mailto:concierge@expensify.com">concierge@expensify.com</a> ' | ||
+ '<a href="mailto:no-concierge@expensify.com">no-concierge@expensify.com</a> ' | ||
+ '<a href="mailto:concierge!@expensify.com">concierge!@expensify.com</a> ' | ||
+ '<a href="mailto:concierge1?@expensify.com">concierge1?@expensify.com</a> '; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); | ||
test('Test markdown and url links with inconsistent starting and closing parens', () => { | ||
const testString = '[google](http://google.com/(something)?after=parens) ' | ||
+ '([google](http://google.com/(something)?after=parens)) ' | ||
+ '([google](https://google.com/)) ' | ||
+ '([google](http://google.com/(something)?after=parens)))) ' | ||
+ '((([google](http://google.com/(something)?after=parens) ' | ||
+ '(http://foo.com/(something)?after=parens) ' | ||
+ '(((http://foo.com/(something)?after=parens ' | ||
+ '(((http://foo.com/(something)?after=parens))) ' | ||
+ 'http://foo.com/(something)?after=parens))) '; | ||
const resultString = '<a href="http://google.com/(something)?after=parens" target="_blank">google</a> ' | ||
+ '(<a href="http://google.com/(something)?after=parens" target="_blank">google</a>) ' | ||
+ '(<a href="https://google.com/" target="_blank">google</a>) ' | ||
+ '(<a href="http://google.com/(something)?after=parens" target="_blank">google</a>))) ' | ||
+ '(((<a href="http://google.com/(something)?after=parens" target="_blank">google</a> ' | ||
+ '(<a href="http://foo.com/(something)?after=parens" target="_blank">http://foo.com/(something)?after=parens</a>) ' | ||
+ '(((<a href="http://foo.com/(something)?after=parens" target="_blank">http://foo.com/(something)?after=parens</a> ' | ||
+ '(((<a href="http://foo.com/(something)?after=parens" target="_blank">http://foo.com/(something)?after=parens</a>))) ' | ||
+ '<a href="http://foo.com/(something)?after=parens" target="_blank">http://foo.com/(something)?after=parens</a>))) '; | ||
expect(parser.replace(testString)).toBe(resultString); | ||
}); |
@@ -6,3 +6,7 @@ module.exports = { | ||
'react/jsx-filename-extension': 'off' | ||
}, | ||
plugins: ['jest'], | ||
env: { | ||
"jest/globals": true | ||
} | ||
}; |
@@ -300,3 +300,49 @@ /** | ||
/** | ||
* Performs API command "Get" | ||
* | ||
* @param {Object} parameters The API call parameters, must contain "returnValueList" | ||
* @param {Domain} [domain] If you want to run this command as the domain account of this domain | ||
* @param {DomainMember} [domainMember] If you want to run this command as specified domain member | ||
* | ||
* @returns {APIDeferred} An APIDeferred representing the promise of this request | ||
*/ | ||
get(parameters) { | ||
const commandName = 'Get'; | ||
requireParameters(['returnValueList'], parameters, commandName); | ||
return performPOSTRequest(commandName, parameters); | ||
}, | ||
/** | ||
* Queues an InboxCallUser so that the inbox team can call the user. | ||
* | ||
* @param {object} parameters | ||
* @param {string} parameters.policyID | ||
* @param {string} parameters.firstName | ||
* @param {string} parameters.lastName | ||
* @param {string} parameters.phoneNumber | ||
* @returns {APIDeferred} | ||
*/ | ||
Inbox_CallUser(parameters) { | ||
const commandName = 'Inbox_CallUser'; | ||
requireParameters(['policyID', 'firstName', 'lastName', 'phoneNumber'], parameters, commandName); | ||
return performPOSTRequest(commandName, parameters); | ||
}, | ||
/** | ||
* Initiate a screen share request with a user. | ||
* | ||
* @param {Object} parameters | ||
* @param {Number} parameters.accountID | ||
* @param {String} parameters.CallSid The external ID of the phone call that both parties using screen share are | ||
* on | ||
* @returns {APIDeferred} | ||
*/ | ||
Inbox_Start_ScreenShare(parameters) { | ||
const commandName = 'Inbox_Start_ScreenShare'; | ||
requireParameters(['accountID', 'CallSid'], parameters, commandName); | ||
return performPOSTRequest(commandName, parameters); | ||
}, | ||
/** | ||
* @param {Object} parameters | ||
* @param {String} parameters.email | ||
@@ -364,3 +410,3 @@ * @param {String} parameters.password | ||
return performPOSTRequest(commandName, { | ||
...parameters, | ||
...parameters, | ||
api_setCookie: false, | ||
@@ -486,3 +532,3 @@ }); | ||
* Fetches the country code based on the location of the request | ||
* | ||
* | ||
* @return {APIDeferred} | ||
@@ -489,0 +535,0 @@ */ |
@@ -6,4 +6,4 @@ import React from 'react'; | ||
import _ from 'underscore'; | ||
import get from 'lodash.get'; | ||
import has from 'lodash.has'; | ||
import get from 'lodash/get'; | ||
import has from 'lodash/has'; | ||
import Str from '../../../str'; | ||
@@ -170,2 +170,3 @@ import DropDown from './dropdown'; | ||
*/ | ||
// eslint-disable-next-line react/no-unsafe | ||
class Combobox extends React.Component { | ||
@@ -270,6 +271,4 @@ constructor(props) { | ||
// We use removeSMSDomain here in case currentValue is a phone number | ||
let defaultSelectedOption = _(this.options).find(o => { | ||
return (Str.isString(o) ? Str.removeSMSDomain(o.value) : o.value) === currentValue | ||
&& !o.isFake; | ||
}); | ||
let defaultSelectedOption = _(this.options).find(o => (Str.isString(o) ? Str.removeSMSDomain(o.value) : o.value) === currentValue | ||
&& !o.isFake); | ||
@@ -697,2 +696,3 @@ // If no default was found and initialText was present then we can use initialText values | ||
this.resetClickAwayHandler(); | ||
// Fire our onChange callback | ||
@@ -699,0 +699,0 @@ this.props.onChange(currentValue); |
@@ -77,2 +77,3 @@ import React from 'react'; | ||
bs4={this.props.bs4} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...option} | ||
@@ -79,0 +80,0 @@ onClick={() => this.handleClick(option)} |
@@ -169,4 +169,3 @@ import React from 'react'; | ||
</a> | ||
) | ||
} | ||
)} | ||
</li> | ||
@@ -173,0 +172,0 @@ ); |
@@ -64,2 +64,5 @@ import React, {Component} from 'react'; | ||
hideEnabledDisabledText: PropTypes.bool, | ||
// Text to display in a tooltip | ||
tooltipText: PropTypes.string, | ||
}; | ||
@@ -82,2 +85,3 @@ | ||
extraClasses: [], | ||
tooltipText: '', | ||
}; | ||
@@ -198,2 +202,3 @@ | ||
hideEnabledDisabledText={this.props.hideEnabledDisabledText} | ||
tooltipText={this.props.tooltipText} | ||
/> | ||
@@ -200,0 +205,0 @@ {this.props.label && this.props.labelOnRight && ( |
/* globals Func, Modal */ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import PropTypes from 'prop-types'; | ||
@@ -38,2 +39,5 @@ import cn from 'classnames'; | ||
hideEnabledDisabledText: PropTypes.bool, | ||
// Text to display in a tooltip | ||
tooltipText: PropTypes.string, | ||
}; | ||
@@ -48,2 +52,3 @@ | ||
hideEnabledDisabledText: false, | ||
tooltipText: '', | ||
}; | ||
@@ -61,2 +66,6 @@ | ||
componentDidMount() { | ||
$(ReactDOM.findDOMNode(this)).tooltip('destroy').tooltip(); | ||
} | ||
/** | ||
@@ -108,3 +117,3 @@ * Gets the value of the field | ||
return ( | ||
<span className={cn('onoffswitch-wrapper', this.props.extraClasses)}> | ||
<span className={cn('onoffswitch-wrapper js_tooltip', this.props.extraClasses)} title={this.props.tooltipText}> | ||
<input | ||
@@ -111,0 +120,0 @@ ref={el => this.checkbox = el} |
/* eslint-disable no-useless-escape */ | ||
import moment from 'moment'; | ||
@@ -420,8 +419,2 @@ const EMAIL_BASE_REGEX = "([\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*@(?:[\\w\\-]+\\.)+[a-z]{2,})"; | ||
/** | ||
* Start and End dates for report, expenses filters, receipts,... | ||
*/ | ||
DEFAULT_START_DATE: moment().subtract(6, 'weeks').format(MOMENT_FORMAT_STRING), | ||
DEFAULT_END_DATE: moment().add(1, 'day').format(MOMENT_FORMAT_STRING), | ||
SHORT_MONTH_SHORT_DAY: 'MMM d', // e.g. Jan 1 | ||
@@ -477,3 +470,3 @@ LONG_YEAR_MONTH_DAY_24_TIME: 'yyyy-MM-dd HH:mm:ss', // e.g. 2020-01-01 20:45:15 | ||
*/ | ||
EXPENSIFY_EMAILS: ['concierge@expensify.com', 'help@expensify.com', 'receipts@expensify.com'], | ||
EXPENSIFY_EMAILS: ['concierge@expensify.com', 'help@expensify.com', 'receipts@expensify.com', 'chronos@expensify.com'], | ||
@@ -718,3 +711,4 @@ /** | ||
IPHONE: 'iphone', | ||
ANDROID: 'android' | ||
ANDROID: 'android', | ||
CHAT: 'chat-expensify-com', | ||
}, | ||
@@ -740,2 +734,5 @@ | ||
INDIVIDUAL_CARD_RAPID_INCREASE_CONFIRMED: 7, | ||
SUSPICIOUS_PAN_ENTRY: 8, | ||
SUSPICIOUS_PAN_ENTRY_CLEARED: 9, | ||
SUSPICIOUS_PAN_ENTRY_CONFIRMED: 10, | ||
} | ||
@@ -827,5 +824,7 @@ }, | ||
'btinternet.com', | ||
'cheerful.com', | ||
'chromeexpensify.com', | ||
'comcast.net', | ||
'cox.net', | ||
'claconnect.com', | ||
'cpa.com', | ||
@@ -852,2 +851,3 @@ 'evernote.user', | ||
'qq.com', | ||
'sasktel.net', | ||
'sbcglobal.net', | ||
@@ -854,0 +854,0 @@ 'verizon.net', |
import Str from './str'; | ||
import TLD_REGEX from './tlds'; | ||
const URL_REGEX = `((https?:\\/\\/(?:www\\.)?)?([-a-z0-9]+?\\.)+(?:${TLD_REGEX})(?:(?:\\?|#|\\/)[-\\w()@:;%\\+.,~#&\\/={}\\[\\]?]*[-\\w()@:;%\\+~#?&\\/={}\\[\\]]|\\/|\\b|(?=_)))`; | ||
const URL_WEBSITE_REGEX = `(https?:\\/\\/)?((?:www\\.)?[-a-z0-9]+?\\.)+(?:${TLD_REGEX})(?:\\:\\d{2,4}|\\b|(?=_))`; | ||
const URL_PATH_REGEX = '(?:\\/[-\\w$@.&+!*"\'(),=%~]*[-\\w~@:%)]|\\/)*'; | ||
const URL_PARAM_REGEX = '(?:\\?[-\\w$@.&+!*"\'()\\/,=%{}:;\\[\\]\\|_]+)?'; | ||
const URL_FRAGMENT_REGEX = '(?:#[-\\w$@.&+!*"\'()[\\],=%;\\/:~]*)?'; | ||
const URL_REGEX = `(${URL_WEBSITE_REGEX}${URL_PATH_REGEX}(?:${URL_PARAM_REGEX}|${URL_FRAGMENT_REGEX})*)`; | ||
@@ -23,3 +27,3 @@ export default class ExpensiMark { | ||
// < is a backtick symbol we are matching on three of them before then after a new line character | ||
regex: /```\n((?:(?!```)[\s\S])+)\n```/g, | ||
regex: /(```[\n]?)((?:(?![\n]?```)[\s\S])+)([\n]?```)/g, | ||
@@ -31,4 +35,5 @@ // We're using a function here to perform an additional replace on the content | ||
// want to do this anywhere else since that would break HTML. | ||
replacement: (match, firstCapturedGroup) => { | ||
const group = firstCapturedGroup.replace(/(?:(?![\n\r])\s)/g, ' '); | ||
// will create styling issues so use   | ||
replacement: (match, _, textWithinFences) => { | ||
const group = textWithinFences.replace(/(?:(?![\n\r])\s)/g, ' '); | ||
return `<pre>${group}</pre>`; | ||
@@ -45,8 +50,20 @@ }, | ||
// Use the url escaped version of a backtick (`) symbol | ||
regex: /\B`(.*?)`\B(?![^<]*<\/pre>)/g, | ||
replacement: '<code>$1</code>', | ||
// Use the url escaped version of a backtick (`) symbol. Mobile platforms do not support lookbehinds, | ||
// so capture the first and third group and place them in the replacement. | ||
regex: /(\B|_)`(.*?)`(\B|_)(?![^<]*<\/pre>)/g, | ||
replacement: '$1<code>$2</code>$3', | ||
}, | ||
/** | ||
* Converts markdown style links to anchor tags e.g. [Expensify](concierge@expensify.com) | ||
* We need to convert before the auto email link rule and the manual link rule since it will not try to create a link | ||
* from an existing anchor tag. | ||
*/ | ||
{ | ||
name: 'email', | ||
regex: /\[([\w\\s\\d!?&#;]+)\]\(([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z]+?(\.[a-zA-Z]{2,6})+)\)/gim, | ||
replacement: '<a href="mailto:$2">$1</a>' | ||
}, | ||
/** | ||
* Converts markdown style links to anchor tags e.g. [Expensify](https://www.expensify.com) | ||
@@ -58,20 +75,48 @@ * We need to convert before the autolink rule since it will not try to create a link | ||
name: 'link', | ||
regex: new RegExp(`\\[([\\w\\s\\d!?]+)\\]\\(${URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi'), | ||
// We use a function here to check if there is already a https:// on the link. If there is not, we force | ||
// the link to be absolute by prepending '//' to the target. | ||
replacement: (match, g1, g2, g3) => { | ||
return `<a href="${g3 && g3.includes('http') ? '' : 'http://'}${g2}" target="_blank">${g1}</a>` | ||
process: (textToProcess, replacement) => { | ||
const regex = new RegExp( | ||
`\\[((?:[\\w\\s\\d!?&#;:\\/\\-\\.\\+=<>,@\\[\\]‘’“”]|(?:<code>.+<\\/code>))+)\\]\\(${URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, | ||
'gi' | ||
); | ||
return this.modifyTextForUrlLinks(regex, textToProcess, replacement); | ||
}, | ||
// We use a function here to check if there is already a https:// on the link. | ||
// If there is not, we force the link to be absolute by prepending '//' to the target. | ||
replacement: (match, g1, g2, g3) => ( | ||
`<a href="${g3 && g3.includes('http') ? '' : 'http://'}${g2}" target="_blank">${g1}</a>` | ||
), | ||
}, | ||
/** | ||
* Automatically links emails that are not in a link. Runs before the autolinker as it will not link an | ||
* email that is in a link | ||
*/ | ||
{ | ||
name: 'autoEmail', | ||
regex: /(?![^<]*>|[^<>]*<\\)([_*~]*?)([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z]+?(\.[a-zA-Z]{2,6})+)(?![^<]*(<\/pre>|<\/code>|<\/a>))/gim, | ||
replacement: '<a href="mailto:$2">$2</a>' | ||
}, | ||
/** | ||
* Automatically link urls. Runs last of our linkers since we want anything manual to link before this, | ||
* and we do not want to break emails. | ||
*/ | ||
{ | ||
name: 'autolink', | ||
// eslint-disable-next-line max-len | ||
regex: new RegExp(`(?![^<]*>|[^<>]*<\\/)([_*~]*?)${URL_REGEX}\\1(?![^<]*(<\\/pre>|<\\/code>))`, 'gi'), | ||
// We use a function here to check if there is already a https:// on the link. If there is not, we force | ||
// the link to be absolute by prepending '//' to the target. | ||
replacement: (match, g1, g2, g3) => { | ||
return `${g1}<a href="${g3 && g3.includes('http') ? '' : 'http://'}${g2}" target="_blank">${g2}</a>${g1}` | ||
process: (textToProcess, replacement) => { | ||
const regex = new RegExp( | ||
`(?![^<]*>|[^<>]*<\\/)([_*~]*?)${URL_REGEX}\\1(?![^<]*(<\\/pre>|<\\/code>))`, | ||
'gi' | ||
); | ||
return this.modifyTextForUrlLinks(regex, textToProcess, replacement); | ||
}, | ||
// We use a function here to check if there is already a https:// on the link. | ||
// If there is not, we force the link to be absolute by prepending '//' to the target. | ||
replacement: (match, g1, g2, g3) => ( | ||
`${g1}<a href="${g3 && g3.includes('http') ? '' : 'http://'}${g2}" target="_blank">${g2}</a>${g1}` | ||
), | ||
}, | ||
@@ -88,3 +133,3 @@ { | ||
name: 'italic', | ||
regex: /(?!_blank">)\b_(.*?)_\b(?![^<]*(<\/pre>|<\/code>))/g, | ||
regex: /(?!_blank">)\b_(.*?)_\b(?![^<]*(<\/pre>|<\/code>|<\/a>))/g, | ||
replacement: '<em>$1</em>' | ||
@@ -97,3 +142,3 @@ }, | ||
name: 'bold', | ||
regex: /\B\*(.*?)\*\B(?![^<]*(<\/pre>|<\/code>))/g, | ||
regex: /\B\*(.*?)\*\B(?![^<]*(<\/pre>|<\/code>|<\/a>))/g, | ||
replacement: '<strong>$1</strong>' | ||
@@ -103,6 +148,15 @@ }, | ||
name: 'strikethrough', | ||
regex: /\B~(.*?)~\B(?![^<]*(<\/pre>|<\/code>))/g, | ||
regex: /\B~(.*?)~\B(?![^<]*(<\/pre>|<\/code>|<\/a>))/g, | ||
replacement: '<del>$1</del>' | ||
}, | ||
{ | ||
name: 'quote', | ||
// We also want to capture a blank line before or after the quote so that we do not add extra spaces. | ||
// block quotes naturally appear on their own line. Blockquotes should not appear in code fences or | ||
// inline code blocks. A single prepending space should be stripped if it exists | ||
regex: /\n?^> ?(?![^<]*(?:<\/pre>|<\/code>))([^\v\n\r]+)\n?/gm, | ||
replacement: '<blockquote>$1</blockquote>' | ||
}, | ||
{ | ||
name: 'newline', | ||
@@ -132,3 +186,7 @@ regex: /\n/g, | ||
replacedText = replacedText.replace(rule.regex, rule.replacement); | ||
if (rule.process) { | ||
replacedText = rule.process(replacedText, rule.replacement); | ||
} else { | ||
replacedText = replacedText.replace(rule.regex, rule.replacement); | ||
} | ||
@@ -143,2 +201,62 @@ // Post-process text after applying regex | ||
} | ||
}; | ||
/** | ||
* Checks matched URLs for validity and replace valid links with html elements | ||
* | ||
* @param {RegExp} regex | ||
* @param {String} textToCheck | ||
* @param {Function} replacement | ||
* | ||
* @returns {String} | ||
*/ | ||
modifyTextForUrlLinks(regex, textToCheck, replacement) { | ||
let match = regex.exec(textToCheck); | ||
let replacedText = ''; | ||
let startIndex = 0; | ||
let abort = false; | ||
while (match !== null) { | ||
// we want to avoid matching email address domains | ||
if ((match.index !== 0) && (textToCheck[match.index - 1] === '@')) { | ||
abort = true; | ||
} | ||
// we want to avoid matching ending ) unless it is a closing parenthesis for the URL | ||
if (textToCheck[(match.index + match[2].length) - 1] === ')' && !match[2].includes('(')) { | ||
match[0] = match[0].substr(0, match[0].length - 1); | ||
match[2] = match[2].substr(0, match[2].length - 1); | ||
} | ||
// remove extra ) parentheses | ||
let brace = 0; | ||
if (match[2][match[2].length - 1] === ')') { | ||
for (let i = 0; i < match[2].length; i++) { | ||
if (match[2][i] === '(') { | ||
brace++; | ||
} | ||
if (match[2][i] === ')') { | ||
brace--; | ||
} | ||
} | ||
if (brace) { | ||
match[0] = match[0].substr(0, match[0].length + brace); | ||
match[2] = match[2].substr(0, match[2].length + brace); | ||
} | ||
} | ||
replacedText = replacedText.concat(textToCheck.substr(startIndex, (match.index - startIndex))); | ||
if (abort) { | ||
replacedText = replacedText.concat(textToCheck.substr(match.index, (match[0].length))); | ||
} else { | ||
replacedText = replacedText.concat(replacement(match[0], match[1], match[2], match[3])); | ||
} | ||
startIndex = match.index + (match[0].length); | ||
// Now we move to the next match that the js regex found in the text | ||
match = regex.exec(textToCheck); | ||
} | ||
if (startIndex < textToCheck.length) replacedText = replacedText.concat(textToCheck.substr(startIndex)); | ||
return replacedText; | ||
} | ||
} |
import _ from 'underscore'; | ||
import has from 'lodash.has'; | ||
import has from 'lodash/has'; | ||
import Log from './Log'; | ||
@@ -4,0 +4,0 @@ |
@@ -226,3 +226,4 @@ /* eslint-disable no-control-regex */ | ||
* Returns the byte size of a character | ||
* @param {String} inputChar You can input more than one character, but it will only return the size of the first one. | ||
* @param {String} inputChar You can input more than one character, but it will only return the size of the first | ||
* one. | ||
* @returns {Number} Byte size of the character | ||
@@ -309,3 +310,2 @@ */ | ||
* | ||
* @deprecated use htmlDecode() instead | ||
* @param {String} str The string to fetch the text value from. | ||
@@ -315,3 +315,7 @@ * @return {String} The text from within the HTML string. | ||
stripHTML(str) { | ||
return this.htmlDecode(str); | ||
if (!this.isString(str)) { | ||
return ''; | ||
} | ||
return str.replace(/<[^>]*>?/gm, ''); | ||
}, | ||
@@ -375,2 +379,13 @@ | ||
/** | ||
* Checks that the string is a valid url | ||
* | ||
* @param {String} string | ||
* | ||
* @returns {Boolean} True if the string is a valid hyperlink | ||
*/ | ||
isValidURL(string) { | ||
return Boolean(String(string).match(CONST.REG_EXP.HYPERLINK)); | ||
}, | ||
/** | ||
* Checks that the string is an email address. | ||
@@ -994,4 +1009,51 @@ * NOTE: TLDs are not just 2-4 characters. Keep this in sync with _inputrules.php | ||
}, | ||
/** | ||
* Get file extension for a given url with or | ||
* without query parameters | ||
* | ||
* @param {String} url | ||
* @returns {String} | ||
*/ | ||
getExtension(url) { | ||
return _.first(_.last(url.split('.')).split('?')).toLowerCase(); | ||
}, | ||
/** | ||
* Takes in a URL and checks if the file extension is PDF | ||
* | ||
* @param {String} url The URL to be checked | ||
* @returns {Boolean} Whether file path is PDF or not | ||
*/ | ||
isPDF(url) { | ||
return this.getExtension(url) === 'pdf'; | ||
}, | ||
/** | ||
* Takes in a URL and checks if the file extension is an image | ||
* that can be rendered by React Native. Do NOT add extensions | ||
* to this list unless they appear in this list and are | ||
* supported by all platforms. | ||
* | ||
* https://reactnative.dev/docs/image#source | ||
* | ||
* @param {String} url | ||
* @returns {Boolean} | ||
*/ | ||
isImage(url) { | ||
return _.contains(['jpeg', 'jpg', 'gif', 'png', 'bmp'], this.getExtension(url)); | ||
}, | ||
/** | ||
* Checks whether the given string is a +@ domain email account, such as | ||
* +@domain.com | ||
* | ||
* @param {String} email | ||
* @return {Boolean} True if is a domain account email, otherwise false. | ||
*/ | ||
isDomainEmail(email) { | ||
return this.startsWith(email, '+@'); | ||
}, | ||
}; | ||
export default Str; |
@@ -1,3 +0,3 @@ | ||
const TLD_REGEX='XN--VERMGENSBERATUNG-PWB|XN--VERMGENSBERATER-CTB|XN--CLCHC0EA0B2G2A9GCD|XN--W4R85EL8FHU5DNRA|TRAVELERSINSURANCE|NORTHWESTERNMUTUAL|XN--XKC2DL3A5EE0H|XN--MGBERP4A5D4AR|XN--MGBAI9AZGQP6J|XN--MGBAH1A3HJKRD|XN--BCK1B9A5DRE4C|XN--5SU34J936BGSG|XN--3OQ18VL8PN36A|XN--XKC2AL3HYE2A|XN--MGBCPQ6GPA1A|XN--MGBA7C0BBN0A|XN--FZYS8D69UVGM|XN--NQV7FS00EMA|XN--MGBC0A9AZCG|XN--MGBAAKC7DVF|XN--MGBA3A4F16A|XN--LGBBAT1AD8J|XN--KCRX77D1X4A|XN--I1B6B1A6A2E|SANDVIKCOROMANT|KERRYPROPERTIES|AMERICANEXPRESS|XN--RVC1E0AM3E|XN--MGBX4CD0AB|XN--MGBI4ECEXP|XN--MGBCA7DZDO|XN--MGBBH1A71E|XN--MGBAYH7GPA|XN--MGBAAM7A8H|XN--MGBA3A3EJT|XN--JLQ61U9W7B|XN--JLQ480N2RG|XN--H2BREG3EVE|XN--FIQ228C5HS|XN--B4W605FERD|XN--80AQECDR1A|XN--6QQ986B3XL|XN--54B7FTA0CC|WEATHERCHANNEL|KERRYLOGISTICS|COOKINGCHANNEL|CANCERRESEARCH|BANANAREPUBLIC|AMERICANFAMILY|AFAMILYCOMPANY|XN--YGBI2AMMX|XN--YFRO4I67O|XN--TIQ49XQYJ|XN--H2BRJ9C8C|XN--FZC2C9E2C|XN--FPCRJ9C3D|XN--ECKVDTC9D|XN--CCKWCXETD|WOLTERSKLUWER|TRAVELCHANNEL|SPREADBETTING|LIFEINSURANCE|INTERNATIONAL|XN--QCKA1PMC|XN--OGBPF8FL|XN--NGBE9E0A|XN--NGBC5AZD|XN--MK1BU44C|XN--MGBT3DHD|XN--MGBPL2FH|XN--MGBGU82A|XN--MGBAB2BD|XN--MGB9AWBF|XN--GCKR3F0F|XN--8Y0A063A|XN--80ASEHDB|XN--80ADXHKS|XN--45BR5CYL|XN--3E0B707E|VERSICHERUNG|SCHOLARSHIPS|LPLFINANCIAL|CONSTRUCTION|XN--ZFR164B|XN--XHQ521B|XN--W4RS40L|XN--VUQ861B|XN--T60B56A|XN--SES554G|XN--S9BRJ9C|XN--ROVU88B|XN--RHQV96G|XN--Q9JYB4C|XN--PGBS0DH|XN--OTU796D|XN--NYQY26A|XN--MIX891F|XN--MGBTX2B|XN--MGBBH1A|XN--KPRY57D|XN--KPRW13D|XN--JVR189M|XN--J6W193G|XN--IMR513N|XN--HXT814E|XN--H2BRJ9C|XN--GK3AT1E|XN--GECRJ9C|XN--G2XX48C|XN--FLW351E|XN--FJQ720A|XN--FCT429K|XN--EFVY88H|XN--D1ACJ3B|XN--CZR694B|XN--CCK2B3B|XN--9KRT00A|XN--80AO21A|XN--6FRZ82G|XN--55QW42G|XN--45BRJ9C|XN--42C2D9A|XN--3HCRJ9C|XN--3DS443G|XN--3BST00M|XN--2SCRJ9C|XN--1QQW23A|XN--1CK2E1B|XN--11B4C3D|WILLIAMHILL|REDUMBRELLA|PROGRESSIVE|PRODUCTIONS|PLAYSTATION|PHOTOGRAPHY|OLAYANGROUP|MOTORCYCLES|LAMBORGHINI|KERRYHOTELS|INVESTMENTS|FOODNETWORK|ENTERPRISES|ENGINEERING|CREDITUNION|CONTRACTORS|CALVINKLEIN|BRIDGESTONE|BLOCKBUSTER|BLACKFRIDAY|BARCLAYCARD|ACCOUNTANTS|XN--Y9A3AQ|XN--WGBL6A|XN--WGBH1C|XN--UNUP4Y|XN--Q7CE6A|XN--PSSY2U|XN--O3CW4H|XN--MXTQ1M|XN--KPUT3I|XN--IO0A7I|XN--FIQZ9S|XN--FIQS8S|XN--FIQ64B|XN--CZRU2D|XN--CZRS0T|XN--CG4BKI|XN--C2BR7G|XN--9ET52U|XN--9DBQ2A|XN--90A3AC|XN--80ASWG|XN--5TZM5G|XN--55QX5D|XN--4GBRIM|XN--45Q11C|XN--3PXU8K|XN--30RR7Y|VOLKSWAGEN|VLAANDEREN|UNIVERSITY|TECHNOLOGY|TATAMOTORS|SWIFTCOVER|SCHAEFFLER|RESTAURANT|REPUBLICAN|REALESTATE|PRUDENTIAL|PROTECTION|PROPERTIES|ONYOURSIDE|NEXTDIRECT|NEWHOLLAND|NATIONWIDE|MITSUBISHI|MANAGEMENT|INDUSTRIES|IMMOBILIEN|HEALTHCARE|FOUNDATION|EXTRASPACE|EUROVISION|CUISINELLA|CREDITCARD|CONSULTING|CAPITALONE|BOEHRINGER|BNPPARIBAS|BASKETBALL|ASSOCIATES|APARTMENTS|ACCOUNTANT|YODOBASHI|XN--VHQUV|XN--TCKWE|XN--QXA6A|XN--P1ACF|XN--NQV7F|XN--NGBRX|XN--L1ACC|XN--J1AMH|XN--J1AEF|XN--FHBEI|XN--E1A4C|XN--D1ALF|XN--C1AVG|XN--90AIS|VACATIONS|TRAVELERS|STOCKHOLM|STATEFARM|STATEBANK|SOLUTIONS|SHANGRILA|SCJOHNSON|RICHARDLI|PRAMERICA|PASSAGENS|PANASONIC|MICROSOFT|MELBOURNE|MARSHALLS|MARKETING|LIFESTYLE|LANDROVER|LANCASTER|KUOKGROUP|INSURANCE|INSTITUTE|HOMESENSE|HOMEGOODS|HOMEDEPOT|HISAMITSU|GOLDPOINT|FURNITURE|FUJIXEROX|FRONTDOOR|FRESENIUS|FIRESTONE|FINANCIAL|FAIRWINDS|EQUIPMENT|EDUCATION|DIRECTORY|COMMUNITY|CHRISTMAS|BLOOMBERG|BARCELONA|AQUARELLE|ANALYTICS|AMSTERDAM|ALLFINANZ|ALFAROMEO|ACCENTURE|YOKOHAMA|XN--QXAM|XN--P1AI|XN--NODE|XN--90AE|WOODSIDE|VERISIGN|VENTURES|VANGUARD|TRAINING|SUPPLIES|STCGROUP|SOFTWARE|SOFTBANK|SHOWTIME|SHOPPING|SERVICES|SECURITY|SAMSCLUB|SAARLAND|RELIANCE|REDSTONE|PROPERTY|PLUMBING|PICTURES|PHARMACY|PARTNERS|OBSERVER|MORTGAGE|MERCKMSD|MEMORIAL|MCKINSEY|MASERATI|MARRIOTT|LUNDBECK|LIGHTING|JPMORGAN|ISTANBUL|IPIRANGA|INFINITI|HOSPITAL|HOLDINGS|HELSINKI|HDFCBANK|GUARDIAN|GRAPHICS|GRAINGER|GOODYEAR|FRONTIER|FOOTBALL|FIRMDALE|FIDELITY|FEEDBACK|EXCHANGE|ETISALAT|ERICSSON|ENGINEER|DOWNLOAD|DISCOVER|DISCOUNT|DIAMONDS|DEMOCRAT|DELOITTE|DELIVERY|COMPUTER|COMMBANK|CLOTHING|CLINIQUE|CLEANING|CITYEATS|CIPRIANI|CATHOLIC|CATERING|CAPETOWN|BUSINESS|BUILDERS|BUDAPEST|BRUSSELS|BROADWAY|BRADESCO|BOUTIQUE|BASEBALL|BARGAINS|BAREFOOT|BARCLAYS|ATTORNEY|ALLSTATE|AIRFORCE|ABUDHABI|ZUERICH|YOUTUBE|YAMAXUN|XFINITY|WINNERS|WINDOWS|WHOSWHO|WEDDING|WEBSITE|WEATHER|WATCHES|WANGGOU|WALMART|TRADING|TOSHIBA|TIFFANY|TICKETS|THEATRE|THEATER|TEMASEK|SYSTEMS|SURGERY|SUPPORT|STORAGE|STAPLES|SINGLES|SHRIRAM|SHIKSHA|SCIENCE|SCHWARZ|SCHMIDT|SANDVIK|SAMSUNG|REXROTH|REVIEWS|RENTALS|RECIPES|REALTOR|POLITIE|PIONEER|PHILIPS|ORIGINS|ORGANIC|OLDNAVY|OKINAWA|NEUSTAR|NETWORK|NETFLIX|NETBANK|MONSTER|MARKETS|LINCOLN|LIMITED|LECLERC|LATROBE|LASALLE|LANXESS|LACAIXA|KOMATSU|KITCHEN|JUNIPER|JEWELRY|ISMAILI|HYUNDAI|HOTMAIL|HOTELES|HOSTING|HOLIDAY|HITACHI|HANGOUT|HAMBURG|GUITARS|GROCERY|GODADDY|GENTING|GALLERY|FUJITSU|FROGANS|FORSALE|FLOWERS|FLORIST|FLIGHTS|FITNESS|FISHING|FINANCE|FERRERO|FERRARI|FASHION|FARMERS|EXPRESS|EXPOSED|DOMAINS|DIGITAL|DENTIST|CRUISES|CRICKET|COURSES|COUPONS|COUNTRY|CORSICA|COOKING|CONTACT|COMPARE|COMPANY|COMCAST|COLOGNE|COLLEGE|CLUBMED|CITADEL|CHINTAI|CHARITY|CHANNEL|CAREERS|CARAVAN|CAPITAL|BUGATTI|BROTHER|BOOKING|BESTBUY|BENTLEY|BAUHAUS|BANAMEX|AVIANCA|AUSPOST|AUDIBLE|AUCTION|ATHLETA|ANDROID|ALIBABA|AGAKHAN|ACADEMY|ABOGADO|ZAPPOS|YANDEX|YACHTS|XIHUAN|WEBCAM|WALTER|VUELOS|VOYAGE|VOTING|VISION|VIRGIN|VILLAS|VIKING|VIAJES|UNICOM|TRAVEL|TOYOTA|TKMAXX|TJMAXX|TIENDA|TENNIS|TATTOO|TARGET|TAOBAO|TAIPEI|SYDNEY|SWATCH|SUZUKI|SUPPLY|STUDIO|STREAM|SOCIAL|SOCCER|SHOUJI|SELECT|SECURE|SEARCH|SCHULE|SCHOOL|SANOFI|SAKURA|SAFETY|RYUKYU|ROGERS|ROCHER|REVIEW|REPORT|REPAIR|REISEN|REALTY|RACING|QUEBEC|PICTET|PHYSIO|PHOTOS|PFIZER|OTSUKA|ORANGE|ORACLE|ONLINE|OLAYAN|OFFICE|NOWRUZ|NORTON|NISSAY|NISSAN|NATURA|NAGOYA|MUTUAL|MUSEUM|MOSCOW|MORMON|MONASH|MOBILE|MATTEL|MARKET|MAKEUP|MAISON|MADRID|LUXURY|LONDON|LOCKER|LIVING|LEFRAK|LAWYER|LATINO|LANCIA|KOSHER|KINDLE|KINDER|KAUFEN|JUEGOS|JOBURG|JAGUAR|INTUIT|INSURE|IMAMAT|HUGHES|HOTELS|HOCKEY|HIPHOP|HERMES|HEALTH|GRATIS|GOOGLE|GLOBAL|GIVING|GEORGE|GARDEN|GALLUP|FUTBOL|FLICKR|FAMILY|EXPERT|EVENTS|ESTATE|ENERGY|EMERCK|DURBAN|DUPONT|DUNLOP|DOCTOR|DIRECT|DESIGN|DENTAL|DEGREE|DEALER|DATSUN|DATING|CRUISE|CREDIT|COUPON|CONDOS|COMSEC|COFFEE|CLINIC|CLAIMS|CIRCLE|CHURCH|CHROME|CHANEL|CENTER|CASINO|CASEIH|CAREER|CAMERA|BROKER|BOSTON|BOSTIK|BHARTI|BERLIN|BEAUTY|BAYERN|AUTHOR|ARAMCO|ANQUAN|AMAZON|ALSTOM|ALSACE|ALIPAY|AIRTEL|AIRBUS|AGENCY|AFRICA|ABBVIE|ABBOTT|ABARTH|YAHOO|XEROX|WORLD|WORKS|WEIBO|WEBER|WATCH|WALES|VOLVO|VODKA|VIDEO|VEGAS|UBANK|TUSHU|TUNES|TRUST|TRADE|TOURS|TOTAL|TORAY|TOOLS|TOKYO|TODAY|TMALL|TIROL|TIRES|TATAR|SWISS|SUCKS|STYLE|STUDY|STORE|STADA|SPORT|SPACE|SOLAR|SMILE|SMART|SLING|SKYPE|SHOES|SHELL|SHARP|SEVEN|SENER|SALON|RUGBY|RODEO|ROCKS|RICOH|REISE|REHAB|RADIO|QUEST|PROMO|PRIME|PRESS|PRAXI|POKER|PLACE|PIZZA|PHOTO|PHONE|PARTY|PARTS|PARIS|OSAKA|OMEGA|NOWTV|NOKIA|NINJA|NIKON|NEXUS|MOVIE|MONEY|MIAMI|MEDIA|MANGO|MACYS|LUPIN|LOTTO|LOTTE|LOCUS|LOANS|LIXIL|LIPSY|LINDE|LILLY|LEXUS|LEGAL|LEASE|LAMER|KYOTO|KOELN|JETZT|IVECO|IRISH|IKANO|HYATT|HOUSE|HORSE|HONDA|HOMES|GUIDE|GUCCI|GROUP|GRIPE|GREEN|GMAIL|GLOBO|GLASS|GLADE|GIVES|GIFTS|GAMES|GALLO|FORUM|FOREX|FINAL|FEDEX|FAITH|EPSON|EMAIL|EDEKA|EARTH|DUBAI|DRIVE|DELTA|DEALS|DANCE|DABUR|CYMRU|CROWN|CODES|COACH|CLOUD|CLICK|CITIC|CISCO|CHEAP|CHASE|CARDS|CANON|BUILD|BOSCH|BOATS|BLACK|BINGO|BIBLE|BEATS|BAIDU|AZURE|AUTOS|AUDIO|ARCHI|APPLE|AMICA|AMFAM|AETNA|ADULT|ACTOR|ZONE|ZERO|ZARA|YOGA|XBOX|WORK|WINE|WIKI|WIEN|WEIR|WANG|VOTO|VOTE|VIVO|VIVA|VISA|VANA|TUBE|TOYS|TOWN|TIPS|TIAA|TEVA|TECH|TEAM|TAXI|TALK|SURF|STAR|SPOT|SONY|SONG|SOHU|SNCF|SKIN|SITE|SINA|SILK|SHOW|SHOP|SHIA|SHAW|SEXY|SEEK|SEAT|SCOT|SAXO|SAVE|SARL|SALE|SAFE|RUHR|RSVP|ROOM|RMIT|RICH|REST|RENT|REIT|READ|RAID|QPON|PROF|PROD|POST|PORN|POHL|PLUS|PLAY|PINK|PING|PICS|PCCW|PARS|PAGE|OPEN|OLLO|NIKE|NICO|NEXT|NEWS|NAVY|NAME|MOTO|MODA|MOBI|MINT|MINI|MENU|MEME|MEET|MAIF|LUXE|LTDA|LOVE|LOFT|LOAN|LIVE|LINK|LIMO|LIKE|LIFE|LIDL|LGBT|LEGO|LAND|KRED|KPMG|KIWI|KDDI|JPRS|JOBS|JEEP|JAVA|ITAU|INFO|IMMO|IMDB|IEEE|ICBC|HSBC|HOST|HGTV|HERE|HELP|HDFC|HAUS|HAIR|GURU|GUGE|GOOG|GOLF|GOLD|GMBH|GIFT|GGEE|GENT|GBIZ|GAME|FUND|FREE|FORD|FOOD|FLIR|FISH|FIRE|FILM|FIDO|FIAT|FAST|FARM|FANS|FAIL|FAGE|ERNI|DVAG|DUCK|DOCS|DISH|DIET|DESI|DELL|DEAL|DCLK|DATE|DATA|CYOU|COOP|COOL|CLUB|CITY|CITI|CHAT|CERN|CBRE|CASH|CASE|CASA|CARS|CARE|CAMP|CALL|CAFE|BUZZ|BOOK|BOND|BOFA|BLUE|BLOG|BING|BIKE|BEST|BEER|BBVA|BANK|BAND|BABY|AUTO|AUDI|ASIA|ASDA|ARTE|ARPA|ARMY|ARAB|AMEX|ALLY|AKDN|AERO|ADAC|ABLE|AARP|ZIP|YUN|YOU|XYZ|XXX|XIN|WTF|WTC|WOW|WME|WIN|WED|VIP|VIN|VIG|VET|UPS|UOL|UNO|UBS|TVS|TUI|TRV|TOP|TJX|THD|TEL|TDK|TCI|TAX|TAB|STC|SRL|SPA|SOY|SKY|SKI|SFR|SEX|SEW|SES|SCB|SCA|SBS|SBI|SAS|SAP|RWE|RUN|RIP|RIO|RIL|REN|RED|QVC|PWC|PUB|PRU|PRO|PNC|PIN|PID|PHD|PET|PAY|OVH|OTT|ORG|OOO|ONL|ONG|ONE|OFF|OBI|NYC|NTT|NRW|NRA|NOW|NHK|NGO|NFL|NEW|NET|NEC|NBA|NAB|MTR|MTN|MSD|MOV|MOM|MOI|MOE|MMA|MLS|MLB|MIT|MIL|MEN|MED|MBA|MAP|MAN|LTD|LPL|LOL|LLP|LLC|LDS|LAW|LAT|KRD|KPN|KIM|KIA|KFH|JOY|JOT|JNJ|JMP|JLL|JIO|JCP|JCB|ITV|IST|INT|INK|ING|INC|IFM|ICU|ICE|IBM|HOW|HOT|HKT|HIV|HBO|GOV|GOT|GOP|GOO|GMX|GMO|GLE|GEA|GDN|GAY|GAP|GAL|FYI|FUN|FTR|FRL|FOX|FOO|FLY|FIT|FAN|EUS|ESQ|EDU|ECO|EAT|DVR|DTV|DOT|DOG|DNP|DIY|DHL|DEV|DDS|DAY|DAD|CSC|CRS|CPA|COM|CFD|CFA|CEO|CEB|CBS|CBN|CBA|CAT|CAR|CAM|CAL|CAB|BZH|BUY|BOX|BOT|BOO|BOM|BMW|BMS|BIZ|BIO|BID|BET|BCN|BCG|BBT|BBC|BAR|AXA|AWS|ART|APP|AOL|ANZ|AIG|AFL|AEG|ADS|ACO|ABC|ABB|AAA|ZW|ZM|ZA|YT|YE|WS|WF|VU|VN|VI|VG|VE|VC|VA|UZ|UY|US|UK|UG|UA|TZ|TW|TV|TT|TR|TO|TN|TM|TL|TK|TJ|TH|TG|TF|TD|TC|SZ|SY|SX|SV|SU|ST|SS|SR|SO|SN|SM|SL|SK|SJ|SI|SH|SG|SE|SD|SC|SB|SA|RW|RU|RS|RO|RE|QA|PY|PW|PT|PS|PR|PN|PM|PL|PK|PH|PG|PF|PE|PA|OM|NZ|NU|NR|NP|NO|NL|NI|NG|NF|NE|NC|NA|MZ|MY|MX|MW|MV|MU|MT|MS|MR|MQ|MP|MO|MN|MM|ML|MK|MH|MG|ME|MD|MC|MA|LY|LV|LU|LT|LS|LR|LK|LI|LC|LB|LA|KZ|KY|KW|KR|KP|KN|KM|KI|KH|KG|KE|JP|JO|JM|JE|IT|IS|IR|IQ|IO|IN|IM|IL|IE|ID|HU|HT|HR|HN|HM|HK|GY|GW|GU|GT|GS|GR|GQ|GP|GN|GM|GL|GI|GH|GG|GF|GE|GD|GB|GA|FR|FO|FM|FK|FJ|FI|EU|ET|ES|ER|EG|EE|EC|DZ|DO|DM|DK|DJ|DE|CZ|CY|CX|CW|CV|CU|CR|CO|CN|CM|CL|CK|CI|CH|CG|CF|CD|CC|CA|BZ|BY|BW|BV|BT|BS|BR|BO|BN|BM|BJ|BI|BH|BG|BF|BE|BD|BB|BA|AZ|AX|AW|AU|AT|AS|AR|AQ|AO|AM|AL|AI|AG|AF|AE|AD|AC'; | ||
const TLD_REGEX='XN--VERMGENSBERATUNG-PWB|XN--VERMGENSBERATER-CTB|XN--CLCHC0EA0B2G2A9GCD|XN--W4R85EL8FHU5DNRA|TRAVELERSINSURANCE|NORTHWESTERNMUTUAL|XN--XKC2DL3A5EE0H|XN--MGBERP4A5D4AR|XN--MGBAI9AZGQP6J|XN--MGBAH1A3HJKRD|XN--BCK1B9A5DRE4C|XN--5SU34J936BGSG|XN--3OQ18VL8PN36A|XN--XKC2AL3HYE2A|XN--MGBCPQ6GPA1A|XN--MGBA7C0BBN0A|XN--FZYS8D69UVGM|XN--NQV7FS00EMA|XN--MGBC0A9AZCG|XN--MGBAAKC7DVF|XN--MGBA3A4F16A|XN--LGBBAT1AD8J|XN--KCRX77D1X4A|XN--I1B6B1A6A2E|SANDVIKCOROMANT|KERRYPROPERTIES|AMERICANEXPRESS|XN--RVC1E0AM3E|XN--MGBX4CD0AB|XN--MGBI4ECEXP|XN--MGBCA7DZDO|XN--MGBBH1A71E|XN--MGBAYH7GPA|XN--MGBAAM7A8H|XN--MGBA3A3EJT|XN--JLQ61U9W7B|XN--JLQ480N2RG|XN--H2BREG3EVE|XN--FIQ228C5HS|XN--B4W605FERD|XN--80AQECDR1A|XN--6QQ986B3XL|XN--54B7FTA0CC|WEATHERCHANNEL|KERRYLOGISTICS|COOKINGCHANNEL|CANCERRESEARCH|BANANAREPUBLIC|AMERICANFAMILY|AFAMILYCOMPANY|XN--YGBI2AMMX|XN--YFRO4I67O|XN--TIQ49XQYJ|XN--H2BRJ9C8C|XN--FZC2C9E2C|XN--FPCRJ9C3D|XN--ECKVDTC9D|XN--CCKWCXETD|WOLTERSKLUWER|TRAVELCHANNEL|SPREADBETTING|LIFEINSURANCE|INTERNATIONAL|XN--QCKA1PMC|XN--OGBPF8FL|XN--NGBE9E0A|XN--NGBC5AZD|XN--MK1BU44C|XN--MGBT3DHD|XN--MGBPL2FH|XN--MGBGU82A|XN--MGBAB2BD|XN--MGB9AWBF|XN--GCKR3F0F|XN--8Y0A063A|XN--80ASEHDB|XN--80ADXHKS|XN--4DBRK0CE|XN--45BR5CYL|XN--3E0B707E|VERSICHERUNG|SCHOLARSHIPS|LPLFINANCIAL|CONSTRUCTION|XN--ZFR164B|XN--XHQ521B|XN--W4RS40L|XN--VUQ861B|XN--T60B56A|XN--SES554G|XN--S9BRJ9C|XN--ROVU88B|XN--RHQV96G|XN--Q9JYB4C|XN--PGBS0DH|XN--OTU796D|XN--NYQY26A|XN--MIX891F|XN--MGBTX2B|XN--MGBBH1A|XN--KPRY57D|XN--KPRW13D|XN--JVR189M|XN--J6W193G|XN--IMR513N|XN--HXT814E|XN--H2BRJ9C|XN--GK3AT1E|XN--GECRJ9C|XN--G2XX48C|XN--FLW351E|XN--FJQ720A|XN--FCT429K|XN--EFVY88H|XN--D1ACJ3B|XN--CZR694B|XN--CCK2B3B|XN--9KRT00A|XN--80AO21A|XN--6FRZ82G|XN--55QW42G|XN--45BRJ9C|XN--42C2D9A|XN--3HCRJ9C|XN--3DS443G|XN--3BST00M|XN--2SCRJ9C|XN--1QQW23A|XN--1CK2E1B|XN--11B4C3D|WILLIAMHILL|REDUMBRELLA|PROGRESSIVE|PRODUCTIONS|PLAYSTATION|PHOTOGRAPHY|OLAYANGROUP|MOTORCYCLES|LAMBORGHINI|KERRYHOTELS|INVESTMENTS|FOODNETWORK|ENTERPRISES|ENGINEERING|CREDITUNION|CONTRACTORS|CALVINKLEIN|BRIDGESTONE|BLOCKBUSTER|BLACKFRIDAY|BARCLAYCARD|ACCOUNTANTS|XN--Y9A3AQ|XN--WGBL6A|XN--WGBH1C|XN--UNUP4Y|XN--Q7CE6A|XN--PSSY2U|XN--O3CW4H|XN--MXTQ1M|XN--KPUT3I|XN--IO0A7I|XN--FIQZ9S|XN--FIQS8S|XN--FIQ64B|XN--CZRU2D|XN--CZRS0T|XN--CG4BKI|XN--C2BR7G|XN--9ET52U|XN--9DBQ2A|XN--90A3AC|XN--80ASWG|XN--5TZM5G|XN--55QX5D|XN--4GBRIM|XN--45Q11C|XN--3PXU8K|XN--30RR7Y|VOLKSWAGEN|VLAANDEREN|UNIVERSITY|TECHNOLOGY|TATAMOTORS|SWIFTCOVER|SCHAEFFLER|RESTAURANT|REPUBLICAN|REALESTATE|PRUDENTIAL|PROTECTION|PROPERTIES|ONYOURSIDE|NEXTDIRECT|NATIONWIDE|MITSUBISHI|MANAGEMENT|INDUSTRIES|IMMOBILIEN|HEALTHCARE|FOUNDATION|EXTRASPACE|EUROVISION|CUISINELLA|CREDITCARD|CONSULTING|CAPITALONE|BOEHRINGER|BNPPARIBAS|BASKETBALL|ASSOCIATES|APARTMENTS|ACCOUNTANT|YODOBASHI|XN--VHQUV|XN--TCKWE|XN--QXA6A|XN--P1ACF|XN--NQV7F|XN--NGBRX|XN--L1ACC|XN--J1AMH|XN--J1AEF|XN--FHBEI|XN--E1A4C|XN--D1ALF|XN--C1AVG|XN--90AIS|VACATIONS|TRAVELERS|STOCKHOLM|STATEFARM|STATEBANK|SOLUTIONS|SHANGRILA|SCJOHNSON|RICHARDLI|PRAMERICA|PASSAGENS|PANASONIC|MICROSOFT|MELBOURNE|MARSHALLS|MARKETING|LIFESTYLE|LANDROVER|LANCASTER|KUOKGROUP|INSURANCE|INSTITUTE|HOMESENSE|HOMEGOODS|HOMEDEPOT|HISAMITSU|GOLDPOINT|FURNITURE|FUJIXEROX|FRONTDOOR|FRESENIUS|FIRESTONE|FINANCIAL|FAIRWINDS|EQUIPMENT|EDUCATION|DIRECTORY|COMMUNITY|CHRISTMAS|BLOOMBERG|BARCELONA|AQUARELLE|ANALYTICS|AMSTERDAM|ALLFINANZ|ALFAROMEO|ACCENTURE|YOKOHAMA|XN--QXAM|XN--P1AI|XN--NODE|XN--90AE|WOODSIDE|VERISIGN|VENTURES|VANGUARD|TRAINING|SUPPLIES|STCGROUP|SOFTWARE|SOFTBANK|SHOWTIME|SHOPPING|SERVICES|SECURITY|SAMSCLUB|SAARLAND|RELIANCE|REDSTONE|PROPERTY|PLUMBING|PICTURES|PHARMACY|PARTNERS|OBSERVER|MORTGAGE|MERCKMSD|MEMORIAL|MCKINSEY|MASERATI|MARRIOTT|LUNDBECK|LIGHTING|JPMORGAN|ISTANBUL|IPIRANGA|INFINITI|HOSPITAL|HOLDINGS|HELSINKI|HDFCBANK|GUARDIAN|GRAPHICS|GRAINGER|GOODYEAR|FRONTIER|FOOTBALL|FIRMDALE|FIDELITY|FEEDBACK|EXCHANGE|ETISALAT|ERICSSON|ENGINEER|DOWNLOAD|DISCOVER|DISCOUNT|DIAMONDS|DEMOCRAT|DELOITTE|DELIVERY|COMPUTER|COMMBANK|CLOTHING|CLINIQUE|CLEANING|CITYEATS|CIPRIANI|CATHOLIC|CATERING|CAPETOWN|BUSINESS|BUILDERS|BUDAPEST|BRUSSELS|BROADWAY|BRADESCO|BOUTIQUE|BASEBALL|BARGAINS|BAREFOOT|BARCLAYS|ATTORNEY|ALLSTATE|AIRFORCE|ABUDHABI|ZUERICH|YOUTUBE|YAMAXUN|XFINITY|WINNERS|WINDOWS|WHOSWHO|WEDDING|WEBSITE|WEATHER|WATCHES|WANGGOU|WALMART|TRADING|TOSHIBA|TIFFANY|TICKETS|THEATRE|THEATER|TEMASEK|SYSTEMS|SURGERY|SUPPORT|STORAGE|STAPLES|SINGLES|SHIKSHA|SCIENCE|SCHWARZ|SCHMIDT|SANDVIK|SAMSUNG|REXROTH|REVIEWS|RENTALS|RECIPES|REALTOR|POLITIE|PIONEER|PHILIPS|ORIGINS|ORGANIC|OLDNAVY|OKINAWA|NEUSTAR|NETWORK|NETFLIX|NETBANK|MONSTER|MARKETS|LINCOLN|LIMITED|LECLERC|LATROBE|LASALLE|LANXESS|LACAIXA|KOMATSU|KITCHEN|JUNIPER|JEWELRY|ISMAILI|HYUNDAI|HOTMAIL|HOTELES|HOSTING|HOLIDAY|HITACHI|HANGOUT|HAMBURG|GUITARS|GROCERY|GODADDY|GENTING|GALLERY|FUJITSU|FROGANS|FORSALE|FLOWERS|FLORIST|FLIGHTS|FITNESS|FISHING|FINANCE|FERRERO|FERRARI|FASHION|FARMERS|EXPRESS|EXPOSED|DOMAINS|DIGITAL|DENTIST|CRUISES|CRICKET|COURSES|COUPONS|COUNTRY|CORSICA|COOKING|CONTACT|COMPARE|COMPANY|COMCAST|COLOGNE|COLLEGE|CLUBMED|CITADEL|CHINTAI|CHARITY|CHANNEL|CAREERS|CARAVAN|CAPITAL|BUGATTI|BROTHER|BOOKING|BESTBUY|BENTLEY|BAUHAUS|BANAMEX|AVIANCA|AUSPOST|AUDIBLE|AUCTION|ATHLETA|ANDROID|ALIBABA|AGAKHAN|ACADEMY|ABOGADO|ZAPPOS|YANDEX|YACHTS|XIHUAN|WEBCAM|WALTER|VUELOS|VOYAGE|VOTING|VISION|VIRGIN|VILLAS|VIKING|VIAJES|UNICOM|TRAVEL|TOYOTA|TKMAXX|TJMAXX|TIENDA|TENNIS|TATTOO|TARGET|TAOBAO|TAIPEI|SYDNEY|SWATCH|SUZUKI|SUPPLY|STUDIO|STREAM|SOCIAL|SOCCER|SHOUJI|SELECT|SECURE|SEARCH|SCHULE|SCHOOL|SANOFI|SAKURA|SAFETY|RYUKYU|ROGERS|ROCHER|REVIEW|REPORT|REPAIR|REISEN|REALTY|RACING|QUEBEC|PICTET|PHYSIO|PHOTOS|PFIZER|OTSUKA|ORANGE|ORACLE|ONLINE|OLAYAN|OFFICE|NOWRUZ|NORTON|NISSAY|NISSAN|NATURA|NAGOYA|MUTUAL|MUSEUM|MOSCOW|MORMON|MONASH|MOBILE|MATTEL|MARKET|MAKEUP|MAISON|MADRID|LUXURY|LONDON|LOCKER|LIVING|LEFRAK|LAWYER|LATINO|LANCIA|KOSHER|KINDLE|KINDER|KAUFEN|JUEGOS|JOBURG|JAGUAR|INTUIT|INSURE|IMAMAT|HUGHES|HOTELS|HOCKEY|HIPHOP|HERMES|HEALTH|GRATIS|GOOGLE|GLOBAL|GIVING|GEORGE|GARDEN|GALLUP|FUTBOL|FLICKR|FAMILY|EXPERT|EVENTS|ESTATE|ENERGY|EMERCK|DURBAN|DUPONT|DUNLOP|DOCTOR|DIRECT|DESIGN|DENTAL|DEGREE|DEALER|DATSUN|DATING|CRUISE|CREDIT|COUPON|CONDOS|COMSEC|COFFEE|CLINIC|CLAIMS|CIRCLE|CHURCH|CHROME|CHANEL|CENTER|CASINO|CAREER|CAMERA|BROKER|BOSTON|BOSTIK|BHARTI|BERLIN|BEAUTY|BAYERN|AUTHOR|ARAMCO|ANQUAN|AMAZON|ALSTOM|ALSACE|ALIPAY|AIRTEL|AIRBUS|AGENCY|AFRICA|ABBVIE|ABBOTT|ABARTH|YAHOO|XEROX|WORLD|WORKS|WEIBO|WEBER|WATCH|WALES|VOLVO|VODKA|VIDEO|VEGAS|UBANK|TUSHU|TUNES|TRUST|TRADE|TOURS|TOTAL|TORAY|TOOLS|TOKYO|TODAY|TMALL|TIROL|TIRES|TATAR|SWISS|SUCKS|STYLE|STUDY|STORE|STADA|SPORT|SPACE|SOLAR|SMILE|SMART|SLING|SKYPE|SHOES|SHELL|SHARP|SEVEN|SENER|SALON|RUGBY|RODEO|ROCKS|RICOH|REISE|REHAB|RADIO|QUEST|PROMO|PRIME|PRESS|PRAXI|POKER|PLACE|PIZZA|PHOTO|PHONE|PARTY|PARTS|PARIS|OSAKA|OMEGA|NOWTV|NOKIA|NINJA|NIKON|NEXUS|MOVIE|MONEY|MIAMI|MEDIA|MANGO|MACYS|LOTTO|LOTTE|LOCUS|LOANS|LIXIL|LIPSY|LINDE|LILLY|LEXUS|LEGAL|LEASE|LAMER|KYOTO|KOELN|JETZT|IVECO|IRISH|IKANO|HYATT|HOUSE|HORSE|HONDA|HOMES|GUIDE|GUCCI|GROUP|GRIPE|GREEN|GMAIL|GLOBO|GLASS|GLADE|GIVES|GIFTS|GAMES|GALLO|FORUM|FOREX|FINAL|FEDEX|FAITH|EPSON|EMAIL|EDEKA|EARTH|DUBAI|DRIVE|DELTA|DEALS|DANCE|DABUR|CYMRU|CROWN|CODES|COACH|CLOUD|CLICK|CITIC|CISCO|CHEAP|CHASE|CARDS|CANON|BUILD|BOSCH|BOATS|BLACK|BINGO|BIBLE|BEATS|BAIDU|AZURE|AUTOS|AUDIO|ARCHI|APPLE|AMICA|AMFAM|AETNA|ADULT|ACTOR|ZONE|ZERO|ZARA|YOGA|XBOX|WORK|WINE|WIKI|WIEN|WEIR|WANG|VOTO|VOTE|VIVO|VIVA|VISA|VANA|TUBE|TOYS|TOWN|TIPS|TIAA|TEVA|TECH|TEAM|TAXI|TALK|SURF|STAR|SPOT|SONY|SONG|SOHU|SNCF|SKIN|SITE|SINA|SILK|SHOW|SHOP|SHIA|SHAW|SEXY|SEEK|SEAT|SCOT|SAXO|SAVE|SARL|SALE|SAFE|RUHR|RSVP|ROOM|RMIT|RICH|REST|RENT|REIT|READ|RAID|QPON|PROF|PROD|POST|PORN|POHL|PLUS|PLAY|PINK|PING|PICS|PCCW|PARS|PAGE|OPEN|OLLO|NIKE|NICO|NEXT|NEWS|NAVY|NAME|MOTO|MODA|MOBI|MINT|MINI|MENU|MEME|MEET|MAIF|LUXE|LTDA|LOVE|LOFT|LOAN|LIVE|LINK|LIMO|LIKE|LIFE|LIDL|LGBT|LEGO|LAND|KRED|KPMG|KIWI|KDDI|JPRS|JOBS|JEEP|JAVA|ITAU|INFO|IMMO|IMDB|IEEE|ICBC|HSBC|HOST|HGTV|HERE|HELP|HDFC|HAUS|HAIR|GURU|GUGE|GOOG|GOLF|GOLD|GMBH|GIFT|GGEE|GENT|GBIZ|GAME|FUND|FREE|FORD|FOOD|FLIR|FISH|FIRE|FILM|FIDO|FIAT|FAST|FARM|FANS|FAIL|FAGE|ERNI|DVAG|DUCK|DOCS|DISH|DIET|DESI|DELL|DEAL|DCLK|DATE|DATA|CYOU|COOP|COOL|CLUB|CITY|CITI|CHAT|CERN|CBRE|CASH|CASE|CASA|CARS|CARE|CAMP|CALL|CAFE|BUZZ|BOOK|BOND|BOFA|BLUE|BLOG|BING|BIKE|BEST|BEER|BBVA|BANK|BAND|BABY|AUTO|AUDI|ASIA|ASDA|ARTE|ARPA|ARMY|ARAB|AMEX|ALLY|AKDN|AERO|ADAC|ABLE|AARP|ZIP|YUN|YOU|XYZ|XXX|XIN|WTF|WTC|WOW|WME|WIN|WED|VIP|VIN|VIG|VET|UPS|UOL|UNO|UBS|TVS|TUI|TRV|TOP|TJX|THD|TEL|TDK|TCI|TAX|TAB|STC|SRL|SPA|SOY|SKY|SKI|SFR|SEX|SEW|SES|SCB|SCA|SBS|SBI|SAS|SAP|RWE|RUN|RIP|RIO|RIL|REN|RED|QVC|PWC|PUB|PRU|PRO|PNC|PIN|PID|PHD|PET|PAY|OVH|OTT|ORG|OOO|ONL|ONG|ONE|OFF|OBI|NYC|NTT|NRW|NRA|NOW|NHK|NGO|NFL|NEW|NET|NEC|NBA|NAB|MTR|MTN|MSD|MOV|MOM|MOI|MOE|MMA|MLS|MLB|MIT|MIL|MEN|MED|MBA|MAP|MAN|LTD|LPL|LOL|LLP|LLC|LDS|LAW|LAT|KRD|KPN|KIM|KIA|KFH|JOY|JOT|JNJ|JMP|JLL|JIO|JCB|ITV|IST|INT|INK|ING|INC|IFM|ICU|ICE|IBM|HOW|HOT|HKT|HIV|HBO|GOV|GOT|GOP|GOO|GMX|GMO|GLE|GEA|GDN|GAY|GAP|GAL|FYI|FUN|FTR|FRL|FOX|FOO|FLY|FIT|FAN|EUS|ESQ|EDU|ECO|EAT|DVR|DTV|DOT|DOG|DNP|DIY|DHL|DEV|DDS|DAY|DAD|CSC|CRS|CPA|COM|CFD|CFA|CEO|CBS|CBN|CBA|CAT|CAR|CAM|CAL|CAB|BZH|BUY|BOX|BOT|BOO|BOM|BMW|BMS|BIZ|BIO|BID|BET|BCN|BCG|BBT|BBC|BAR|AXA|AWS|ART|APP|AOL|ANZ|AIG|AFL|AEG|ADS|ACO|ABC|ABB|AAA|ZW|ZM|ZA|YT|YE|WS|WF|VU|VN|VI|VG|VE|VC|VA|UZ|UY|US|UK|UG|UA|TZ|TW|TV|TT|TR|TO|TN|TM|TL|TK|TJ|TH|TG|TF|TD|TC|SZ|SY|SX|SV|SU|ST|SS|SR|SO|SN|SM|SL|SK|SJ|SI|SH|SG|SE|SD|SC|SB|SA|RW|RU|RS|RO|RE|QA|PY|PW|PT|PS|PR|PN|PM|PL|PK|PH|PG|PF|PE|PA|OM|NZ|NU|NR|NP|NO|NL|NI|NG|NF|NE|NC|NA|MZ|MY|MX|MW|MV|MU|MT|MS|MR|MQ|MP|MO|MN|MM|ML|MK|MH|MG|ME|MD|MC|MA|LY|LV|LU|LT|LS|LR|LK|LI|LC|LB|LA|KZ|KY|KW|KR|KP|KN|KM|KI|KH|KG|KE|JP|JO|JM|JE|IT|IS|IR|IQ|IO|IN|IM|IL|IE|ID|HU|HT|HR|HN|HM|HK|GY|GW|GU|GT|GS|GR|GQ|GP|GN|GM|GL|GI|GH|GG|GF|GE|GD|GB|GA|FR|FO|FM|FK|FJ|FI|EU|ET|ES|ER|EG|EE|EC|DZ|DO|DM|DK|DJ|DE|CZ|CY|CX|CW|CV|CU|CR|CO|CN|CM|CL|CK|CI|CH|CG|CF|CD|CC|CA|BZ|BY|BW|BV|BT|BS|BR|BO|BN|BM|BJ|BI|BH|BG|BF|BE|BD|BB|BA|AZ|AX|AW|AU|AT|AS|AR|AQ|AO|AM|AL|AI|AG|AF|AE|AD|AC|SJC|RNO|LAX'; | ||
export default TLD_REGEX; |
{ | ||
"name": "expensify-common", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"author": "Expensify, Inc.", | ||
@@ -12,4 +12,5 @@ "description": "Expensify libraries and components shared across different repos", | ||
"test": "jest", | ||
"lint": "eslint lib/", | ||
"patch": "npm --no-git-tag-version version patch", | ||
"update-tlds": "curl -s https://data.iana.org/TLD/tlds-alpha-by-domain.txt | sed '1d' | awk '{print length, $0}' - | sort -n -r | cut -d \" \" -f2- | tr '\\n' '|' | sed s'/.$//' | printf \"const TLD_REGEX='$(cat -)';\\n\\nexport default TLD_REGEX;\\n\" > lib/tlds.jsx" | ||
"update-tlds": "echo \"$(curl -s https://data.iana.org/TLD/tlds-alpha-by-domain.txt | sed '1d' | awk '{print length, $0}' - | sort -n -r | cut -d \" \" -f2- )|SJC|RNO|LAX\" | tr '\\n' '|' | sed s'/.$//' | printf \"const TLD_REGEX='$(cat -)';\\n\\nexport default TLD_REGEX;\\n\" > lib/tlds.jsx" | ||
}, | ||
@@ -21,22 +22,23 @@ "repository": { | ||
"dependencies": { | ||
"classnames": "2.2.5", | ||
"classnames": "2.3.1", | ||
"clipboard": "2.0.4", | ||
"html-entities": "^1.3.1", | ||
"jquery": "3.3.1", | ||
"lodash.get": "4.4.2", | ||
"lodash.has": "4.5.2", | ||
"moment": "2.20.1", | ||
"lodash": "4.17.21", | ||
"prop-types": "15.7.2", | ||
"react": "16.12.0", | ||
"react-dom": "16.12.0", | ||
"simply-deferred": "3.0.0", | ||
"underscore": "1.9.1" | ||
"semver": "^7.3.4", | ||
"simply-deferred": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5", | ||
"underscore": "1.13.1" | ||
}, | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.0.0", | ||
"babel-jest": "^26.3.0", | ||
"eslint-config-expensify": "2.0.7", | ||
"eslint-plugin-jest": "^24.1.5", | ||
"grunt": "*", | ||
"grunt-chokidar": "1.0.2", | ||
"babelify": "10.0.0", | ||
"grunt-eslint": "22.0.0", | ||
"grunt-chokidar": "1.0.2", | ||
"@babel/preset-env": "^7.0.0", | ||
"jest": "^26.4.2", | ||
@@ -43,0 +45,0 @@ "jit-grunt": "^0.10.0" |
@@ -29,4 +29,2 @@ # `expensify-common` | ||
# Deploying a Change (Expensify Only) | ||
1. Create a new branch from master and run `npm run patch` | ||
2. Push up the changes, create a PR, and get it reviewed and merged | ||
3. Publish a new version by following the instructions [here](https://stackoverflow.com/c/expensify/questions/7216) | ||
1. Once the PR has been merged update the `package.json` commit hash in any repos with a dependency on `expensify-common` |
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable and can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
293154
11
52
6753
10
30
1
+ Addedlodash@4.17.21
+ Addedsemver@^7.3.4
+ Addedclassnames@2.3.1(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedsemver@7.7.1(transitive)
+ Addedunderscore@1.13.1(transitive)
- Removedlodash.get@4.4.2
- Removedlodash.has@4.5.2
- Removedmoment@2.20.1
- Removedclassnames@2.2.5(transitive)
- Removedlodash.get@4.4.2(transitive)
- Removedlodash.has@4.5.2(transitive)
- Removedmoment@2.20.1(transitive)
- Removedsimply-deferred@3.0.0(transitive)
- Removedunderscore@1.9.1(transitive)
Updatedclassnames@2.3.1
Updatedunderscore@1.13.1