expensify-common 2.0.118 → 2.0.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/CONST.d.ts CHANGED
@@ -386,6 +386,10 @@ declare const CONST: {
386
386
  * @type RegExp
387
387
  */
388
388
  readonly EMOJI_RULE: RegExp;
389
+ /**
390
+ * Regex to match a piece of text or @here, needed for both shortMention and userMention
391
+ */
392
+ readonly PRE_MENTION_TEXT_PART: "(@here|[a-zA-Z0-9.!$%&+=?^\\`{|}-]?)";
389
393
  };
390
394
  readonly REPORT: {
391
395
  /**
package/dist/CONST.js CHANGED
@@ -394,6 +394,10 @@ const CONST = {
394
394
  * @type RegExp
395
395
  */
396
396
  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,
397
+ /**
398
+ * Regex to match a piece of text or @here, needed for both shortMention and userMention
399
+ */
400
+ PRE_MENTION_TEXT_PART: '(@here|[a-zA-Z0-9.!$%&+=?^\\`{|}-]?)',
397
401
  },
398
402
  REPORT: {
399
403
  /**
@@ -269,7 +269,7 @@ class ExpensiMark {
269
269
  */
270
270
  {
271
271
  name: 'userMentions',
272
- regex: new RegExp(`(@here|[a-zA-Z0-9.!$%&+=?^\`{|}-]?)(@${Constants.CONST.REG_EXP.EMAIL_PART}|@${Constants.CONST.REG_EXP.PHONE_PART})(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>))`, 'gim'),
272
+ regex: new RegExp(`${Constants.CONST.REG_EXP.PRE_MENTION_TEXT_PART}(@${Constants.CONST.REG_EXP.EMAIL_PART}|@${Constants.CONST.REG_EXP.PHONE_PART})(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>))`, 'gim'),
273
273
  replacement: (_extras, match, g1, g2) => {
274
274
  const phoneNumberRegex = new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`);
275
275
  const mention = g2.slice(1);
@@ -374,6 +374,35 @@ class ExpensiMark {
374
374
  replacement: '$1<a href="mailto:$2">$2</a>',
375
375
  rawInputReplacement: '$1<a href="mailto:$2" data-raw-href="$2" data-link-variant="auto">$2</a>',
376
376
  },
377
+ /**
378
+ * This regex matches a short user mention in a string.
379
+ * A short-mention is a string that starts with the '@' symbol and is followed by a valid user's primary login without the email domain part
380
+ * Ex: @john.doe, @user12345, but NOT @user@email.com
381
+ *
382
+ * Notes:
383
+ * Phone is not a valid short mention.
384
+ * In reality these "short-mentions" are just possible candidates, because the parser has no way of verifying if there exists a user named ex: @john.examplename.
385
+ * The actual verification whether these mentions are pointing to real users is done in specific projects using ExpensiMark.
386
+ * Nevertheless, "@john.examplename" is a correct possible short-mention, and so would be parsed.
387
+ * This behaviour is similar to treating every user@something as valid user login.
388
+ *
389
+ * This regex will correctly preserve any @here mentions, the same way as "userMention" rule.
390
+ */
391
+ {
392
+ name: 'shortMentions',
393
+ regex: new RegExp(`${Constants.CONST.REG_EXP.PRE_MENTION_TEXT_PART}(@(?=((?=[\\w]+[\\w'#%+-]+(?:\\.[\\w'#%+-]+)*)[\\w\\.'#%+-]{1,64}(?= |_|\\b))(?!([:\\/\\\\]))(?<end>.*))(?!here)\\S{3,254}(?=\\k<end>$))(?!((?:(?!<a).)+)?<\\/a>|[^<]*(<\\/pre>|<\\/code>|<\\/mention-user>|<\\/mention-here>))`, 'gim'),
394
+ replacement: (_extras, match, g1, g2) => {
395
+ if (!str_1.default.isValidMention(match)) {
396
+ return match;
397
+ }
398
+ return `${g1}<mention-short>${g2}</mention-short>`;
399
+ },
400
+ },
401
+ {
402
+ name: 'hereMentionAfterShortMentions',
403
+ regex: /(<\/mention-short>)(@here)(?=\b)/gm,
404
+ replacement: '$1<mention-here>$2</mention-here>',
405
+ },
377
406
  {
378
407
  // Use \B in this case because \b doesn't match * or ~.
379
408
  // \B will match everything that \b doesn't, so it works
@@ -607,7 +636,7 @@ class ExpensiMark {
607
636
  },
608
637
  {
609
638
  name: 'reportMentions',
610
- regex: /<mention-report reportID="(\d+)"(?: *\/>|><\/mention-report>)/gi,
639
+ regex: /<mention-report reportID="?(\d+)"?(?: *\/>|><\/mention-report>)/gi,
611
640
  replacement: (extras, _match, g1, _offset, _string) => {
612
641
  const reportToNameMap = extras.reportIDToName;
613
642
  if (!reportToNameMap || !reportToNameMap[g1]) {
@@ -619,7 +648,7 @@ class ExpensiMark {
619
648
  },
620
649
  {
621
650
  name: 'userMention',
622
- regex: /(?:<mention-user accountID="(\d+)"(?: *\/>|><\/mention-user>))|(?:<mention-user>(.*?)<\/mention-user>)/gi,
651
+ regex: /(?:<mention-user accountID="?(\d+)"?(?: *\/>|><\/mention-user>))|(?:<mention-user>(.*?)<\/mention-user>)/gi,
623
652
  replacement: (extras, _match, g1, g2, _offset, _string) => {
624
653
  var _a, _b;
625
654
  if (g1) {
@@ -686,7 +715,7 @@ class ExpensiMark {
686
715
  },
687
716
  {
688
717
  name: 'reportMentions',
689
- regex: /<mention-report reportID="(\d+)" *\/>/gi,
718
+ regex: /<mention-report reportID="?(\d+)"?(?: *\/>|><\/mention-report>)/gi,
690
719
  replacement: (extras, _match, g1, _offset, _string) => {
691
720
  const reportToNameMap = extras.reportIDToName;
692
721
  if (!reportToNameMap || !reportToNameMap[g1]) {
@@ -698,15 +727,18 @@ class ExpensiMark {
698
727
  },
699
728
  {
700
729
  name: 'userMention',
701
- regex: /<mention-user accountID="(\d+)" *\/>/gi,
702
- replacement: (extras, _match, g1, _offset, _string) => {
730
+ regex: /(?:<mention-user accountID="?(\d+)"?(?: *\/>|><\/mention-user>))|(?:<mention-user>(.*?)<\/mention-user>)/gi,
731
+ replacement: (extras, _match, g1, g2, _offset, _string) => {
703
732
  var _a, _b;
704
- const accountToNameMap = extras.accountIDToName;
705
- if (!accountToNameMap || !accountToNameMap[g1]) {
706
- ExpensiMark.Log.alert('[ExpensiMark] Missing account name', { accountID: g1 });
707
- return '@Hidden';
733
+ if (g1) {
734
+ const accountToNameMap = extras.accountIDToName;
735
+ if (!accountToNameMap || !accountToNameMap[g1]) {
736
+ ExpensiMark.Log.alert('[ExpensiMark] Missing account name', { accountID: g1 });
737
+ return '@Hidden';
738
+ }
739
+ return `@${str_1.default.removeSMSDomain((_b = (_a = extras.accountIDToName) === null || _a === void 0 ? void 0 : _a[g1]) !== null && _b !== void 0 ? _b : '')}`;
708
740
  }
709
- return `@${str_1.default.removeSMSDomain((_b = (_a = extras.accountIDToName) === null || _a === void 0 ? void 0 : _a[g1]) !== null && _b !== void 0 ? _b : '')}`;
741
+ return str_1.default.removeSMSDomain(g2);
710
742
  },
711
743
  },
712
744
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expensify-common",
3
- "version": "2.0.118",
3
+ "version": "2.0.124",
4
4
  "author": "Expensify, Inc.",
5
5
  "description": "Expensify libraries and components shared across different repos",
6
6
  "homepage": "https://expensify.com",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "git+ssh://git@github.com/Expensify/JS-Libs.git"
28
+ "url": "git+ssh://git@github.com/Expensify/expensify-common.git"
29
29
  },
30
30
  "dependencies": {
31
31
  "awesome-phonenumber": "^5.4.0",
@@ -43,7 +43,7 @@
43
43
  "ua-parser-js": "^1.0.38"
44
44
  },
45
45
  "devDependencies": {
46
- "@babel/preset-env": "^7.25.4",
46
+ "@babel/preset-env": "^7.26.0",
47
47
  "@babel/preset-typescript": "^7.24.7",
48
48
  "@lwc/eslint-plugin-lwc": "^1.8.2",
49
49
  "@types/jest": "^29.5.13",
@@ -51,8 +51,8 @@
51
51
  "@types/lodash": "^4.17.10",
52
52
  "@types/react-dom": "^18.3.5",
53
53
  "@types/ua-parser-js": "^0.7.39",
54
- "@typescript-eslint/eslint-plugin": "^8.3.0",
55
- "@typescript-eslint/parser": "^8.3.0",
54
+ "@typescript-eslint/eslint-plugin": "^8.22.0",
55
+ "@typescript-eslint/parser": "^8.23.0",
56
56
  "babel-jest": "^29.0.0",
57
57
  "babelify": "10.0.0",
58
58
  "eslint": "^8.57.1",