expensify-common 2.0.188 → 2.0.190

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.
Files changed (78) hide show
  1. package/dist/Logger.js +11 -1
  2. package/dist/esm/API.d.ts +11 -0
  3. package/dist/esm/API.js +786 -0
  4. package/dist/esm/APIDeferred.d.ts +7 -0
  5. package/dist/esm/APIDeferred.js +216 -0
  6. package/dist/esm/BrowserDetect.d.ts +19 -0
  7. package/dist/esm/BrowserDetect.js +105 -0
  8. package/dist/esm/CLI.js +37 -29
  9. package/dist/esm/CONST.d.ts +1727 -0
  10. package/dist/esm/CONST.js +1847 -0
  11. package/dist/esm/Cookie.d.ts +68 -0
  12. package/dist/esm/Cookie.js +159 -0
  13. package/dist/esm/CredentialsWrapper.d.ts +32 -0
  14. package/dist/esm/CredentialsWrapper.js +46 -0
  15. package/dist/esm/Device.d.ts +8 -0
  16. package/dist/esm/Device.js +24 -0
  17. package/dist/esm/ExpenseRule.d.ts +39 -0
  18. package/dist/esm/ExpenseRule.js +77 -0
  19. package/dist/esm/ExpensiMark.d.ts +197 -0
  20. package/dist/esm/ExpensiMark.js +1374 -0
  21. package/dist/esm/Func.d.ts +40 -0
  22. package/dist/esm/Func.js +69 -0
  23. package/dist/esm/Log.d.ts +3 -0
  24. package/dist/esm/Log.js +35 -0
  25. package/dist/esm/Logger.d.ts +82 -0
  26. package/dist/esm/Logger.js +148 -0
  27. package/dist/esm/Network.d.ts +6 -0
  28. package/dist/esm/Network.js +168 -0
  29. package/dist/esm/Num.d.ts +95 -0
  30. package/dist/esm/Num.js +190 -0
  31. package/dist/esm/PageEvent.d.ts +25 -0
  32. package/dist/esm/PageEvent.js +22 -0
  33. package/dist/esm/PubSub.d.ts +2 -0
  34. package/dist/esm/PubSub.js +111 -0
  35. package/dist/esm/ReportHistoryStore.d.ts +8 -0
  36. package/dist/esm/ReportHistoryStore.js +199 -0
  37. package/dist/esm/SafeString.js +2 -2
  38. package/dist/esm/Templates.d.ts +58 -0
  39. package/dist/esm/Templates.js +196 -0
  40. package/dist/esm/Url.d.ts +10 -0
  41. package/dist/esm/Url.js +15 -0
  42. package/dist/esm/components/CopyText.d.ts +45 -0
  43. package/dist/esm/components/CopyText.js +56 -0
  44. package/dist/esm/components/StepProgressBar.d.ts +26 -0
  45. package/dist/esm/components/StepProgressBar.js +40 -0
  46. package/dist/esm/components/form/element/combobox.d.ts +231 -0
  47. package/dist/esm/components/form/element/combobox.js +812 -0
  48. package/dist/esm/components/form/element/dropdown.d.ts +35 -0
  49. package/dist/esm/components/form/element/dropdown.js +61 -0
  50. package/dist/esm/components/form/element/dropdownItem.d.ts +55 -0
  51. package/dist/esm/components/form/element/dropdownItem.js +113 -0
  52. package/dist/esm/components/form/element/onOffSwitch.d.ts +94 -0
  53. package/dist/esm/components/form/element/onOffSwitch.js +167 -0
  54. package/dist/esm/components/form/element/switch.d.ts +58 -0
  55. package/dist/esm/components/form/element/switch.js +98 -0
  56. package/dist/esm/fastMerge.d.ts +9 -0
  57. package/dist/esm/fastMerge.js +58 -0
  58. package/dist/esm/index.d.ts +22 -0
  59. package/dist/esm/index.js +22 -0
  60. package/dist/esm/jquery.expensifyIframify.d.ts +9 -0
  61. package/dist/esm/jquery.expensifyIframify.js +397 -0
  62. package/dist/esm/md5.d.ts +2 -0
  63. package/dist/esm/md5.js +170 -0
  64. package/dist/esm/mixins/PubSub.d.ts +20 -0
  65. package/dist/esm/mixins/PubSub.js +47 -0
  66. package/dist/esm/mixins/extraClasses.d.ts +8 -0
  67. package/dist/esm/mixins/extraClasses.js +37 -0
  68. package/dist/esm/mixins/validationClasses.d.ts +12 -0
  69. package/dist/esm/mixins/validationClasses.js +30 -0
  70. package/dist/esm/str.d.ts +604 -0
  71. package/dist/esm/str.js +1036 -0
  72. package/dist/esm/tlds.d.ts +2 -0
  73. package/dist/esm/tlds.js +2 -0
  74. package/dist/esm/utils.d.ts +30 -0
  75. package/dist/esm/utils.js +65 -0
  76. package/dist/index.d.ts +1 -0
  77. package/dist/index.js +8 -1
  78. package/package.json +221 -4
@@ -0,0 +1,68 @@
1
+ declare namespace _default {
2
+ export let NAME_LAST_PAGE: string;
3
+ export let NAME_LAST_REPORTS_PAGE: string;
4
+ export let NAME_STASHED_SUPPORT: string;
5
+ export let NAME_WEB_COOKIE: string;
6
+ export let NAME_EXPENSES_VIEW_MODE: string;
7
+ export let MOBILE_APP_VERSION: string;
8
+ export let TWO_FACTOR_DEVICE_TOKEN: string;
9
+ export { enabled };
10
+ export { remove };
11
+ export { get };
12
+ export { getJSON };
13
+ export { has };
14
+ export { getHelpLink };
15
+ export { set };
16
+ }
17
+ export default _default;
18
+ /**
19
+ * Detects if cookies are currently enabled in the browser
20
+ * by trying to create a cookie, see if it exists, and delete it afterwards again.
21
+ *
22
+ * @returns {Boolean} True if cookies are enabled, otherwise false.
23
+ */
24
+ declare function enabled(): boolean;
25
+ /**
26
+ * Deletes a cookie.
27
+ *
28
+ * @param {String} name The name of the cookie to delete.
29
+ */
30
+ declare function remove(name: string): void;
31
+ /**
32
+ * Fetches the value of a cookie.
33
+ *
34
+ * @param {String} name The name of the cookie to fetch.
35
+ * @returns {String|null} The value of the cookie.
36
+ */
37
+ declare function get(name: string): string | null;
38
+ /**
39
+ * Parses a cookie value to JSON.
40
+ * Returns a default value specified by param or null.
41
+ *
42
+ * @param {String} name
43
+ * @param {Any|null} defaultValue
44
+ *
45
+ * @returns {Any|null}
46
+ */
47
+ declare function getJSON(name: string, defaultValue?: Any | null): Any | null;
48
+ /**
49
+ * Find a cookie that has been set.
50
+ *
51
+ * @param {String} name Name of the cookie to find
52
+ * @returns {Boolean} Whether or not the cookie is set
53
+ */
54
+ declare function has(name: string): boolean;
55
+ /**
56
+ * Returns help link when cookies are enabled or null.
57
+ *
58
+ * @returns {(String|null)}
59
+ */
60
+ declare function getHelpLink(): (string | null);
61
+ /**
62
+ * Sets the value of a cookie and when it will expire.
63
+ *
64
+ * @param {String} name The name of the cookie.
65
+ * @param {String} value The value of the cookie.
66
+ * @param {Number} [expiredays] The number of days until the cookie expires.
67
+ */
68
+ declare function set(name: string, value: string, expiredays?: number): void;
@@ -0,0 +1,159 @@
1
+ import BrowserDetect from './BrowserDetect';
2
+ const CONST = {
3
+ /**
4
+ * Cookie storing the the name of the page we visited the last time
5
+ */
6
+ NAME_LAST_PAGE: 'lastPage',
7
+ /**
8
+ * Cookie storing the name of the reports page we visited the last time (e.g. reports, inbox)
9
+ */
10
+ NAME_LAST_REPORTS_PAGE: 'lastReportsPage',
11
+ /**
12
+ * Cookie storing a user's restricted-access support token
13
+ */
14
+ NAME_STASHED_SUPPORT: '_stashedSupportLogin',
15
+ /**
16
+ * Cookie set by expensify web that's used to identify a request as coming from web.
17
+ */
18
+ NAME_WEB_COOKIE: 'expensifyWeb',
19
+ /**
20
+ * Cookie storing the mode the user wants to use when viewing the expenses page.
21
+ */
22
+ NAME_EXPENSES_VIEW_MODE: 'expensesPageViewMode',
23
+ /**
24
+ * Cookie set that denotes a mobile request
25
+ */
26
+ MOBILE_APP_VERSION: 'appversion',
27
+ /**
28
+ * Two-Factor Auth device token
29
+ */
30
+ TWO_FACTOR_DEVICE_TOKEN: 'stashedTwoFactorLogin',
31
+ };
32
+ /**
33
+ * Deletes a cookie.
34
+ *
35
+ * @param {String} name The name of the cookie to delete.
36
+ */
37
+ function remove(name) {
38
+ const date = new Date();
39
+ document.cookie = `${name}=; expires=${date.toUTCString()}`;
40
+ }
41
+ /**
42
+ * Sets the value of a cookie and when it will expire.
43
+ *
44
+ * @param {String} name The name of the cookie.
45
+ * @param {String} value The value of the cookie.
46
+ * @param {Number} [expiredays] The number of days until the cookie expires.
47
+ */
48
+ function set(name, value, expiredays) {
49
+ // Get expiry date, set
50
+ const exdate = new Date();
51
+ exdate.setDate(exdate.getDate() + expiredays);
52
+ document.cookie = `${name}=${encodeURIComponent(value)}${expiredays === null ? '' : `;expires=${exdate.toUTCString()}`}`;
53
+ }
54
+ /**
55
+ * Detects if cookies are currently enabled in the browser
56
+ * by trying to create a cookie, see if it exists, and delete it afterwards again.
57
+ *
58
+ * @returns {Boolean} True if cookies are enabled, otherwise false.
59
+ */
60
+ function enabled() {
61
+ // Check they have cookies enabled
62
+ const cookieName = `cookieTest_${Math.floor(Math.random() * 1000)}`;
63
+ const cookieValue = 'enabled';
64
+ set(cookieName, cookieValue, 1);
65
+ const result = document.cookie.indexOf(cookieName) >= 0 || false;
66
+ if (result) {
67
+ remove(cookieName);
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Fetches the value of a cookie.
73
+ *
74
+ * @param {String} name The name of the cookie to fetch.
75
+ * @returns {String|null} The value of the cookie.
76
+ */
77
+ function get(name) {
78
+ if (!name || document.cookie.length <= 0) {
79
+ return null;
80
+ }
81
+ let start;
82
+ let end;
83
+ start = document.cookie.indexOf(`${name}=`);
84
+ if (start !== -1) {
85
+ start = start + name.length + 1;
86
+ end = document.cookie.indexOf(';', start);
87
+ if (end === -1) {
88
+ end = document.cookie.length;
89
+ }
90
+ return decodeURIComponent(document.cookie.substring(start, end));
91
+ }
92
+ return null;
93
+ }
94
+ /**
95
+ * Parses a cookie value to JSON.
96
+ * Returns a default value specified by param or null.
97
+ *
98
+ * @param {String} name
99
+ * @param {Any|null} defaultValue
100
+ *
101
+ * @returns {Any|null}
102
+ */
103
+ function getJSON(name, defaultValue = null) {
104
+ let data;
105
+ try {
106
+ data = JSON.parse(get(name));
107
+ }
108
+ catch (_a) {
109
+ data = defaultValue;
110
+ }
111
+ return data;
112
+ }
113
+ /**
114
+ * Find a cookie that has been set.
115
+ *
116
+ * @param {String} name Name of the cookie to find
117
+ * @returns {Boolean} Whether or not the cookie is set
118
+ */
119
+ function has(name) {
120
+ return get(name) !== null;
121
+ }
122
+ /**
123
+ * Returns help link when cookies are enabled or null.
124
+ *
125
+ * @returns {(String|null)}
126
+ */
127
+ function getHelpLink() {
128
+ if (enabled()) {
129
+ return null;
130
+ }
131
+ let helpLink = 'http://www.google.com/search?q=enable+cookies';
132
+ // Set up help link according to browser
133
+ if (BrowserDetect.browser === BrowserDetect.BROWSERS.EXPLORER) {
134
+ helpLink = 'https://support.microsoft.com/en-us/help/17442/windows-internet-explorer-delete-manage-cookies';
135
+ }
136
+ else if (BrowserDetect.browser === BrowserDetect.BROWSERS.SAFARI) {
137
+ helpLink = 'https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac';
138
+ }
139
+ else if (BrowserDetect.browser === BrowserDetect.BROWSERS.MOZILLA) {
140
+ helpLink = 'http://support.mozilla.com/en-US/kb/Enabling%20and%20disabling%20cookies';
141
+ }
142
+ else if (BrowserDetect.browser === BrowserDetect.BROWSERS.OPERA) {
143
+ helpLink = 'http://www.opera.com/help/tutorials/security/privacy/';
144
+ }
145
+ else if (BrowserDetect.browser === BrowserDetect.BROWSERS.CHROME) {
146
+ helpLink = 'http://www.google.com/support/chrome/bin/answer.py?answer=95647';
147
+ }
148
+ else if (BrowserDetect.browser === BrowserDetect.BROWSERS.EDGE) {
149
+ helpLink = 'https://privacy.microsoft.com/en-us/windows-10-microsoft-edge-and-privacy';
150
+ }
151
+ return helpLink;
152
+ }
153
+ export default Object.assign({ enabled,
154
+ remove,
155
+ get,
156
+ getJSON,
157
+ has,
158
+ getHelpLink,
159
+ set }, CONST);
@@ -0,0 +1,32 @@
1
+ export default CredentialWrapper;
2
+ declare namespace CredentialWrapper {
3
+ /**
4
+ * @returns {Promise} Promise resolves to an object containing partnerUserID and partnerUserSecret
5
+ */
6
+ function getCredentials(): Promise<any>;
7
+ /**
8
+ * @returns {Object} Object contains randomly generated partnerUserID and partnerUserSecret
9
+ */
10
+ function generateCredentials(): Object;
11
+ /**
12
+ * @param {Object} credentials
13
+ * @param {String} credentials.partnerUserID
14
+ * @param {String} credentials.partnerUserSecret
15
+ *
16
+ * @returns {Promise} Promise resolves to an object containing partnerUserID and partnerUserSecret
17
+ */
18
+ function setCredentials(credentials: {
19
+ partnerUserID: string;
20
+ partnerUserSecret: string;
21
+ }): Promise<any>;
22
+ /**
23
+ * @returns {Promise}
24
+ */
25
+ function clearCredentials(): Promise<any>;
26
+ }
27
+ export namespace LOGIN_PARTNER_DETAILS {
28
+ let CREDENTIALS_KEY: string;
29
+ let EXPENSIFY_PARTNER_PREFIX: string;
30
+ let PARTNER_NAME: string;
31
+ let PARTNER_PASSWORD: string;
32
+ }
@@ -0,0 +1,46 @@
1
+ import localForage from 'localforage';
2
+ const LOGIN_PARTNER_DETAILS = {
3
+ CREDENTIALS_KEY: 'DEVICE_SESSION_CREDENTIALS',
4
+ EXPENSIFY_PARTNER_PREFIX: 'expensify.',
5
+ PARTNER_NAME: 'chat-expensify-com',
6
+ PARTNER_PASSWORD: 'e21965746fd75f82bb66',
7
+ };
8
+ const CredentialWrapper = {
9
+ /**
10
+ * @returns {Promise} Promise resolves to an object containing partnerUserID and partnerUserSecret
11
+ */
12
+ getCredentials() {
13
+ return localForage.getItem(LOGIN_PARTNER_DETAILS.CREDENTIALS_KEY);
14
+ },
15
+ /**
16
+ * @returns {Object} Object contains randomly generated partnerUserID and partnerUserSecret
17
+ */
18
+ generateCredentials() {
19
+ return {
20
+ partnerUserID: LOGIN_PARTNER_DETAILS.EXPENSIFY_PARTNER_PREFIX + crypto.randomUUID(),
21
+ partnerUserSecret: crypto.randomUUID(),
22
+ };
23
+ },
24
+ /**
25
+ * @param {Object} credentials
26
+ * @param {String} credentials.partnerUserID
27
+ * @param {String} credentials.partnerUserSecret
28
+ *
29
+ * @returns {Promise} Promise resolves to an object containing partnerUserID and partnerUserSecret
30
+ */
31
+ setCredentials(credentials) {
32
+ if (!credentials.partnerUserID || !credentials.partnerUserSecret) {
33
+ // eslint-disable-next-line prefer-promise-reject-errors
34
+ return Promise.reject('Invalid credential pair');
35
+ }
36
+ return localForage.setItem(LOGIN_PARTNER_DETAILS.CREDENTIALS_KEY, credentials);
37
+ },
38
+ /**
39
+ * @returns {Promise}
40
+ */
41
+ clearCredentials() {
42
+ return localForage.removeItem(LOGIN_PARTNER_DETAILS.CREDENTIALS_KEY);
43
+ },
44
+ };
45
+ export default CredentialWrapper;
46
+ export { LOGIN_PARTNER_DETAILS };
@@ -0,0 +1,8 @@
1
+ type DeviceInfo = {
2
+ os: string | undefined;
3
+ osVersion: string | undefined;
4
+ deviceName: string | undefined;
5
+ deviceVersion: string | undefined;
6
+ };
7
+ declare function getOSAndName(): DeviceInfo;
8
+ export { getOSAndName, };
@@ -0,0 +1,24 @@
1
+ import { UAParser } from 'ua-parser-js';
2
+ function getOSAndName() {
3
+ var _a;
4
+ const parser = new UAParser();
5
+ const { browser, os } = parser.getResult();
6
+ let osVersion = os.version;
7
+ // Detection logic inspired by UAParser guide on iOS 26:
8
+ // https://docs.uaparser.dev/guides/how-to-detect-ios-26-using-javascript.html
9
+ const [osMajor, osMinor] = ((_a = os.version) !== null && _a !== void 0 ? _a : '').split('.');
10
+ const osMajorInt = parseInt(osMajor, 10);
11
+ const osMinorInt = parseInt(osMinor, 10);
12
+ if (browser.name === 'Mobile Safari' && browser.major === '26' && os.name === 'iOS' && (osMajorInt > 18 || (osMajorInt === 18 && osMinorInt >= 6))) {
13
+ osVersion = '26';
14
+ }
15
+ return {
16
+ os: os.name,
17
+ osVersion,
18
+ deviceName: browser.name,
19
+ deviceVersion: browser.version,
20
+ };
21
+ }
22
+ export {
23
+ // eslint-disable-next-line import/prefer-default-export
24
+ getOSAndName, };
@@ -0,0 +1,39 @@
1
+ export default class ExpenseRule {
2
+ /**
3
+ * Checks the passed value against the actual based on what the condition (matches, greater, less than, etc.)
4
+ *
5
+ * @param {string} condition
6
+ * @param {Mixed} ruleValue
7
+ * @param {Mixed} transactionValue
8
+ * @returns {boolean}
9
+ */
10
+ static checkCondition(condition: string, ruleValue: Mixed, transactionValue: Mixed): boolean;
11
+ /**
12
+ * Creates a new instance of this class.
13
+ *
14
+ * @param {Object|Array} ruleArray
15
+ */
16
+ constructor(ruleArray: Object | any[]);
17
+ /**
18
+ * Returns the applyWhen array associated with the passed field
19
+ * i.e. field == category returns [field: 'category', condition: 'matches', value: 'car']
20
+ *
21
+ * @param {string} field
22
+ *
23
+ * @returns {Object}
24
+ */
25
+ getApplyWhenByField(field: string): Object;
26
+ /**
27
+ * Get the externalID saved deep in the tax field
28
+ *
29
+ * @returns {String}
30
+ */
31
+ getExternalTaxID(): string;
32
+ /**
33
+ * Checks if the passed expense matches this expense rule
34
+ *
35
+ * @param {SExpense3} expense
36
+ * @returns {boolean}
37
+ */
38
+ isMatch(expense: SExpense3): boolean;
39
+ }
@@ -0,0 +1,77 @@
1
+ export default class ExpenseRule {
2
+ /**
3
+ * Creates a new instance of this class.
4
+ *
5
+ * @param {Object|Array} ruleArray
6
+ */
7
+ constructor(ruleArray) {
8
+ // It's not 100% certain that `ruleArray` is an array or an object, so support both of them so the app doesn't crash
9
+ if (Array.isArray(ruleArray)) {
10
+ for (const [key, value] of ruleArray.entries()) {
11
+ this[key] = value;
12
+ }
13
+ }
14
+ else if (ruleArray && typeof ruleArray === 'object') {
15
+ for (const key of Object.keys(ruleArray)) {
16
+ this[key] = ruleArray[key];
17
+ }
18
+ }
19
+ }
20
+ /**
21
+ * Returns the applyWhen array associated with the passed field
22
+ * i.e. field == category returns [field: 'category', condition: 'matches', value: 'car']
23
+ *
24
+ * @param {string} field
25
+ *
26
+ * @returns {Object}
27
+ */
28
+ getApplyWhenByField(field) {
29
+ return this.applyWhen.find((conditions) => conditions.field === field) || {};
30
+ }
31
+ /**
32
+ * Get the externalID saved deep in the tax field
33
+ *
34
+ * @returns {String}
35
+ */
36
+ getExternalTaxID() {
37
+ return this.tax.field_id_TAX.externalID || '';
38
+ }
39
+ /**
40
+ * Checks if the passed expense matches this expense rule
41
+ *
42
+ * @param {SExpense3} expense
43
+ * @returns {boolean}
44
+ */
45
+ isMatch(expense) {
46
+ let isMatch = true;
47
+ for (const conditions of this.applyWhen) {
48
+ switch (conditions.field) {
49
+ case 'category':
50
+ if (!ExpenseRule.checkCondition(conditions.condition, conditions.value, expense.getCategory())) {
51
+ isMatch = false;
52
+ }
53
+ break;
54
+ default:
55
+ break;
56
+ }
57
+ }
58
+ return isMatch;
59
+ }
60
+ /**
61
+ * Checks the passed value against the actual based on what the condition (matches, greater, less than, etc.)
62
+ *
63
+ * @param {string} condition
64
+ * @param {Mixed} ruleValue
65
+ * @param {Mixed} transactionValue
66
+ * @returns {boolean}
67
+ */
68
+ static checkCondition(condition, ruleValue, transactionValue) {
69
+ // Add more condition types (Greater than, Less than, Contains) below
70
+ switch (condition) {
71
+ case 'matches':
72
+ return ruleValue === transactionValue;
73
+ default:
74
+ return false;
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,197 @@
1
+ import Logger from './Logger';
2
+ type Extras = {
3
+ reportIDToName?: Record<string, string>;
4
+ accountIDToName?: Record<string, string>;
5
+ /**
6
+ * @deprecated Replaced with mediaAttributeCachingFn
7
+ */
8
+ cacheVideoAttributes?: (vidSource: string, attrs: string) => void;
9
+ /**
10
+ * @deprecated Replaced with mediaAttributeCache
11
+ */
12
+ videoAttributeCache?: Record<string, string>;
13
+ /**
14
+ * Function used to cache HTML tag attributes during conversion to and from Markdown
15
+ * @param mediaSource URI to media source
16
+ * @param attrs Additional attributes to be cached
17
+ */
18
+ mediaAttributeCachingFn?: (mediaSource: string, attrs: string) => void;
19
+ /**
20
+ * Key/value cache for HTML tag attributes, where the key is media source URI, value is cached attributes
21
+ */
22
+ mediaAttributeCache?: Record<string, string>;
23
+ };
24
+ export type { Extras };
25
+ type ReplacementFn = (extras: Extras, ...matches: string[]) => string;
26
+ type Replacement = ReplacementFn | string;
27
+ type ProcessFn = (textToProcess: string, replacement: Replacement, shouldKeepRawInput: boolean) => string;
28
+ type CommonRule = {
29
+ name: string;
30
+ replacement: Replacement;
31
+ rawInputReplacement?: Replacement;
32
+ pre?: (input: string) => string;
33
+ post?: (input: string) => string;
34
+ shouldSkipProcessing?: (textToCheck: string) => boolean;
35
+ };
36
+ type RuleWithRegex = CommonRule & {
37
+ regex: RegExp;
38
+ };
39
+ type RuleWithProcess = CommonRule & {
40
+ process: ProcessFn;
41
+ };
42
+ type Rule = RuleWithRegex | RuleWithProcess;
43
+ type ReplaceOptions = {
44
+ extras?: Extras;
45
+ filterRules?: string[];
46
+ disabledRules?: string[];
47
+ shouldEscapeText?: boolean;
48
+ shouldKeepRawInput?: boolean;
49
+ };
50
+ type TruncateOptions = {
51
+ ellipsis?: string;
52
+ truncateLastWord?: boolean;
53
+ slop?: number;
54
+ removeImageTag?: boolean;
55
+ };
56
+ declare function resolveAttributeCache(extras?: Extras): {
57
+ attrCachingFn: ((vidSource: string, attrs: string) => void) | undefined;
58
+ attrCache: Record<string, string> | undefined;
59
+ };
60
+ /**
61
+ * replace block element with '\n' if :
62
+ * 1. We have text within the element.
63
+ * 2. The text does not end with a new line.
64
+ * 3. It's not the last element in the string.
65
+ */
66
+ declare function replaceBlockElementWithNewLine(htmlString: string): string;
67
+ /** Check if the input text includes only the open or the close tag of an element. */
68
+ declare function containsNonPairTag(textToCheck: string): boolean;
69
+ /**
70
+ * Truncate HTML string and keep tag safe.
71
+ * pulled from https://github.com/huang47/nodejs-html-truncate/blob/master/lib/truncate.js
72
+ */
73
+ declare function truncateHTML(html: string, maxLength: number, options?: TruncateOptions): string;
74
+ export default class ExpensiMark {
75
+ static Log: Logger;
76
+ /**
77
+ * Set the logger to use for logging inside of the ExpensiMark class
78
+ * @param logger - The logger object to use
79
+ */
80
+ static setLogger(logger: Logger): void;
81
+ /** Rules to apply to the text */
82
+ rules: Rule[];
83
+ /**
84
+ * The list of regex replacements to do on a HTML comment for converting it to markdown.
85
+ * Order of rules is important
86
+ */
87
+ htmlToMarkdownRules: RuleWithRegex[];
88
+ /**
89
+ * The list of rules to covert the HTML to text.
90
+ * Order of rules is important
91
+ */
92
+ htmlToTextRules: RuleWithRegex[];
93
+ /**
94
+ * The list of rules that we have to exclude in shouldKeepWhitespaceRules list.
95
+ */
96
+ whitespaceRulesToDisable: string[];
97
+ /**
98
+ * The list of rules that have to be applied when shouldKeepWhitespace flag is true.
99
+ */
100
+ filterRules: (rule: Rule) => boolean;
101
+ /**
102
+ * Filters rules to determine which should keep whitespace.
103
+ */
104
+ shouldKeepWhitespaceRules: Rule[];
105
+ /**
106
+ * maxQuoteDepth is the maximum depth of nested quotes that we want to support.
107
+ */
108
+ maxQuoteDepth: number;
109
+ /**
110
+ * currentQuoteDepth is the current depth of nested quotes that we are processing.
111
+ */
112
+ currentQuoteDepth: number;
113
+ constructor();
114
+ /**
115
+ * Retrieves the HTML ruleset based on the provided filter rules, disabled rules, and shouldKeepRawInput flag.
116
+ * @param filterRules - An array of rule names to filter the ruleset.
117
+ * @param disabledRules - An array of rule names to disable in the ruleset.
118
+ * @param shouldKeepRawInput - A boolean flag indicating whether to keep raw input.
119
+ */
120
+ getHtmlRuleset(filterRules: string[], disabledRules: string[], shouldKeepRawInput: boolean): Rule[];
121
+ /**
122
+ * Replaces markdown with html elements
123
+ *
124
+ * @param text - Text to parse as markdown
125
+ * @param [options] - Options to customize the markdown parser
126
+ * @param [options.filterRules=[]] - An array of name of rules as defined in this class.
127
+ * If not provided, all available rules will be applied.
128
+ * @param [options.shouldEscapeText=true] - Whether or not the text should be escaped
129
+ * @param [options.disabledRules=[]] - An array of name of rules as defined in this class.
130
+ * If not provided, all available rules will be applied. If provided, the rules in the array will be skipped.
131
+ */
132
+ replace(text: string, { filterRules, shouldEscapeText, shouldKeepRawInput, disabledRules, extras }?: ReplaceOptions): string;
133
+ /**
134
+ * Checks matched URLs for validity and replace valid links with html elements
135
+ */
136
+ modifyTextForUrlLinks(regex: RegExp, textToCheck: string, replacement: ReplacementFn): string;
137
+ /**
138
+ * Checks matched Emails for validity and replace valid links with html elements
139
+ */
140
+ modifyTextForEmailLinks(regex: RegExp, textToCheck: string, replacement: ReplacementFn, shouldKeepRawInput: boolean): string;
141
+ /**
142
+ * Unpacks nested quote HTML tags that have been packed by the 'quote' rule in this.rules for shouldKeepRawInput = false
143
+ *
144
+ * For example, it parses the following HTML:
145
+ * <blockquote>
146
+ * quote 1
147
+ * <blockquote>
148
+ * quote 2
149
+ * </blockquote>
150
+ * quote 3
151
+ * </blockquote>
152
+ *
153
+ * into:
154
+ * <blockquote> quote 1</blockquote>
155
+ * <blockquote><blockquote> quote 2</blockquote>
156
+ * <blockquote> quote 3</blockquote>
157
+ *
158
+ * Note that there will always be only a single closing tag, even if multiple opening tags exist.
159
+ * Only one closing tag is needed to detect if a nested quote has ended.
160
+ */
161
+ static unpackNestedQuotes(text: string): string;
162
+ /**
163
+ * Replaces HTML with markdown
164
+ */
165
+ htmlToMarkdown(htmlString: string, extras?: Extras): string;
166
+ /**
167
+ * Convert HTML to text
168
+ */
169
+ htmlToText(htmlString: string, extras?: Extras): string;
170
+ /**
171
+ * Main text to html 'quote' parsing logic.
172
+ * Removes &gt;( ) from text and recursively calls replace function to process nested quotes and build blockquote HTML result.
173
+ * @param shouldKeepRawInput determines if the raw input should be kept for nested quotes.
174
+ */
175
+ replaceQuoteText(text: string, shouldKeepRawInput: boolean): {
176
+ replacedText: string;
177
+ shouldAddSpace: boolean;
178
+ };
179
+ getAttributeCache: typeof resolveAttributeCache;
180
+ replaceBlockElementWithNewLine: typeof replaceBlockElementWithNewLine;
181
+ containsNonPairTag: typeof containsNonPairTag;
182
+ truncateHTML: typeof truncateHTML;
183
+ /**
184
+ * @returns array or undefined if exception occurs when executing regex matching
185
+ */
186
+ extractLinksInMarkdownComment(comment: string): string[] | undefined;
187
+ /**
188
+ * Compares two markdown comments and returns a list of the links removed in a new comment.
189
+ */
190
+ getRemovedMarkdownLinks(oldComment: string, newComment: string): string[];
191
+ /**
192
+ * Escapes the content of an HTML attribute value
193
+ * @param content - string content that possible contains HTML
194
+ * @returns original MD content escaped for use in HTML attribute value
195
+ */
196
+ escapeAttributeContent(content: string): string;
197
+ }