expensify-common 2.0.15 → 2.0.16

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
@@ -774,6 +774,7 @@ declare const CONST: {
774
774
  readonly prompt: "What software are you moving to and why?";
775
775
  };
776
776
  };
777
+ readonly VIDEO_EXTENSIONS: readonly ["mp4", "mov", "avi", "wmv", "flv", "mkv", "webm", "3gp", "m4v", "mpg", "mpeg", "ogv"];
777
778
  };
778
779
  /**
779
780
  * UI Constants
package/dist/CONST.js CHANGED
@@ -817,6 +817,7 @@ const CONST = {
817
817
  prompt: 'What software are you moving to and why?',
818
818
  },
819
819
  },
820
+ VIDEO_EXTENSIONS: ['mp4', 'mov', 'avi', 'wmv', 'flv', 'mkv', 'webm', '3gp', 'm4v', 'mpg', 'mpeg', 'ogv'],
820
821
  };
821
822
  exports.CONST = CONST;
822
823
  /**
@@ -39,7 +39,13 @@ declare type Rule = {
39
39
  declare type ExtrasObject = {
40
40
  reportIDToName?: Record<string, string>;
41
41
  accountIDToName?: Record<string, string>;
42
+ cacheVideoAttributes?: (vidSource: string, attrs: string) => void;
42
43
  };
44
+
45
+ declare type ExtraParamsForReplaceFunc = {
46
+ videoAttributeCache?: Record<string, string>;
47
+ };
48
+
43
49
  export default class ExpensiMark {
44
50
  static Log: Logger;
45
51
  static setLogger(logger: Logger): void;
@@ -66,11 +72,13 @@ export default class ExpensiMark {
66
72
  filterRules,
67
73
  shouldEscapeText,
68
74
  shouldKeepRawInput,
75
+ extras,
69
76
  }?: {
70
77
  filterRules?: Name[];
71
78
  disabledRules?: Name[];
72
79
  shouldEscapeText?: boolean;
73
80
  shouldKeepRawInput?: boolean;
81
+ extras?: ExtraParamsForReplaceFunc;
74
82
  },
75
83
  ): string;
76
84
  /**
@@ -33,6 +33,7 @@ const Logger_1 = __importDefault(require("./Logger"));
33
33
  const Utils = __importStar(require("./utils"));
34
34
  const MARKDOWN_LINK_REGEX = new RegExp(`\\[([^\\][]*(?:\\[[^\\][]*][^\\][]*)*)]\\(${UrlPatterns.MARKDOWN_URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi');
35
35
  const MARKDOWN_IMAGE_REGEX = new RegExp(`\\!(?:\\[([^\\][]*(?:\\[[^\\][]*][^\\][]*)*)])?\\(${UrlPatterns.MARKDOWN_URL_REGEX}\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi');
36
+ const MARKDOWN_VIDEO_REGEX = new RegExp(`\\!(?:\\[([^\\][]*(?:\\[[^\\][]*][^\\][]*)*)])?\\(((${UrlPatterns.MARKDOWN_URL_REGEX})\\.(?:${Constants.CONST.VIDEO_EXTENSIONS.join('|')}))\\)(?![^<]*(<\\/pre>|<\\/code>))`, 'gi');
36
37
  const SLACK_SPAN_NEW_LINE_TAG = '<span class="c-mrkdwn__br" data-stringify-type="paragraph-break" style="box-sizing: inherit; display: block; height: unset;"></span>';
37
38
  class ExpensiMark {
38
39
  /**
@@ -129,7 +130,33 @@ class ExpensiMark {
129
130
  replacement: '<h1>$1</h1>',
130
131
  },
131
132
  /**
132
- * Converts markdown style images to img tags e.g. ![Expensify](https://www.expensify.com/attachment.png)
133
+ * Converts markdown style video to video tags e.g. ![Expensify](https://www.expensify.com/attachment.mp4)
134
+ * We need to convert before image rules since they will not try to create a image tag from an existing video URL
135
+ * Extras arg could contain the attribute cache for the video tag which is cached during the html-to-markdown conversion
136
+ */
137
+ {
138
+ name: 'video',
139
+ regex: MARKDOWN_VIDEO_REGEX,
140
+ /**
141
+ * @param {string} match
142
+ * @param {string} videoName - The first capture group - video name
143
+ * @param {string} videoSource - The second capture group - video URL
144
+ * @param {any[]} args - The rest capture groups and `extras` object. args[args.length-1] will the `extras` object
145
+ * @return {string} Returns the HTML video tag
146
+ */
147
+ replacement: (match, videoName, videoSource, ...args) => {
148
+ const extras = args[args.length - 1];
149
+ const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];
150
+ return `<video data-expensify-source="${str_1.default.sanitizeURL(videoSource)}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;
151
+ },
152
+ rawInputReplacement: (match, videoName, videoSource, ...args) => {
153
+ const extras = args[args.length - 1];
154
+ const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];
155
+ return `<video data-expensify-source="${str_1.default.sanitizeURL(videoSource)}" data-raw-href="${videoSource}" data-link-variant="${typeof videoName === 'string' ? 'labeled' : 'auto'}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;
156
+ },
157
+ },
158
+ /**
159
+ * Converts markdown style images to image tags e.g. ![Expensify](https://www.expensify.com/attachment.png)
133
160
  * We need to convert before linking rules since they will not try to create a link from an existing img
134
161
  * tag.
135
162
  * Additional sanitization is done to the alt attribute to prevent parsing it further to html by later
@@ -476,6 +503,29 @@ class ExpensiMark {
476
503
  return `!(${g2})`;
477
504
  },
478
505
  },
506
+ {
507
+ name: 'video',
508
+ regex: /<video[^><]*data-expensify-source\s*=\s*(['"])(\S*?)\1(.*?)>([^><]*)<\/video>*(?![^<][\s\S]*?(<\/pre>|<\/code>))/gi,
509
+ /**
510
+ * @param {string} match The full match
511
+ * @param {string} g1 {string} The first capture group
512
+ * @param {string} videoSource - the second capture group - video source (video URL)
513
+ * @param {string} videoAttrs - the third capture group - video attributes (data-expensify-width, data-expensify-height, etc...)
514
+ * @param {string} videoName - the fourth capture group will be the video file name (the text between opening and closing video tags)
515
+ * @param {any[]} args The rest of the arguments. args[args.length-1] will the `extras` object
516
+ * @returns {string} Returns the markdown video tag
517
+ */
518
+ replacement: (match, g1, videoSource, videoAttrs, videoName, ...args) => {
519
+ const extras = args[args.length - 1];
520
+ if (videoAttrs && extras && extras.cacheVideoAttributes && typeof extras.cacheVideoAttributes === 'function') {
521
+ extras.cacheVideoAttributes(videoSource, videoAttrs);
522
+ }
523
+ if (videoName) {
524
+ return `![${videoName}](${videoSource})`;
525
+ }
526
+ return `!(${videoSource})`;
527
+ },
528
+ },
479
529
  {
480
530
  name: 'reportMentions',
481
531
  regex: /<mention-report reportID="(\d+)" *\/>/gi,
@@ -630,7 +680,7 @@ class ExpensiMark {
630
680
  *
631
681
  * @returns {String}
632
682
  */
633
- replace(text, { filterRules = [], shouldEscapeText = true, shouldKeepRawInput = false, disabledRules = [] } = {}) {
683
+ replace(text, { filterRules = [], shouldEscapeText = true, shouldKeepRawInput = false, disabledRules = [], extras } = {}) {
634
684
  // This ensures that any html the user puts into the comment field shows as raw html
635
685
  let replacedText = shouldEscapeText ? Utils.escape(text) : text;
636
686
  const rules = this.getHtmlRuleset(filterRules, disabledRules, shouldKeepRawInput);
@@ -640,11 +690,12 @@ class ExpensiMark {
640
690
  replacedText = rule.pre(replacedText);
641
691
  }
642
692
  const replacementFunction = shouldKeepRawInput && rule.rawInputReplacement ? rule.rawInputReplacement : rule.replacement;
693
+ const replacementFnWithExtraParams = typeof replacementFunction === 'function' ? (...args) => replacementFunction(...args, extras) : replacementFunction;
643
694
  if (rule.process) {
644
- replacedText = rule.process(replacedText, replacementFunction, shouldKeepRawInput);
695
+ replacedText = rule.process(replacedText, replacementFnWithExtraParams, shouldKeepRawInput);
645
696
  }
646
697
  else {
647
- replacedText = replacedText.replace(rule.regex, replacementFunction);
698
+ replacedText = replacedText.replace(rule.regex, replacementFnWithExtraParams);
648
699
  }
649
700
  // Post-process text after applying regex
650
701
  if (rule.post) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expensify-common",
3
- "version": "2.0.15",
3
+ "version": "2.0.16",
4
4
  "author": "Expensify, Inc.",
5
5
  "description": "Expensify libraries and components shared across different repos",
6
6
  "homepage": "https://expensify.com",