expensify-common 2.0.223 → 2.0.225

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/API.js CHANGED
@@ -280,16 +280,6 @@ function API(network, args) {
280
280
  const newParameters = Object.assign(Object.assign({}, parameters), { api_setCookie: false });
281
281
  return performPOSTRequest(commandName, newParameters);
282
282
  },
283
- /**
284
- * @param {Object} parameters
285
- * @param {String} parameters.email
286
- * @returns {ExpensifyAPIDeferred}
287
- */
288
- Domain_RequestAccess(parameters) {
289
- const commandName = 'Domain_RequestAccess';
290
- requireParameters(['email'], parameters, commandName);
291
- return performPOSTRequest(commandName, parameters);
292
- },
293
283
  /**
294
284
  * @param {Object} parameters
295
285
  * @param {String[]} parameters.emailList
@@ -269,14 +269,14 @@ function findKnownTldEnd(text, dotPosition) {
269
269
  return undefined;
270
270
  }
271
271
  /**
272
- * Validates a hostname and records a linkable prefix before a later malformed label.
273
- * Preserves known-TLD prefixes before oversized continuations without recovering text inside an invalid leading label.
272
+ * Validates a hostname and records a linkable prefix before malformed punctuation in a later label.
273
+ * Rejects the whole hostname when a label or its complete length exceeds a DNS limit.
274
274
  *
275
275
  * @param text - Text containing the URL candidate.
276
276
  * @param hostnameStart - Index of the hostname's first character.
277
277
  * @param hostnameEnd - Index immediately after the hostname.
278
278
  * @param hasProtocol - Whether the URL allows hostnames without a known TLD, including single-label hosts.
279
- * @returns The hostname validity and any prefix that can be linked before a malformed or oversized continuation.
279
+ * @returns The hostname validity and any prefix that can be linked before malformed punctuation.
280
280
  */
281
281
  function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
282
282
  let hostnameContentEnd = hostnameEnd;
@@ -288,7 +288,6 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
288
288
  }
289
289
  let labelStart = hostnameStart;
290
290
  let validHostnamePrefixEnd;
291
- let validKnownTldPrefixEnd;
292
291
  for (let index = hostnameStart; index <= hostnameContentEnd; index++) {
293
292
  if (index !== hostnameContentEnd && text[index] !== '.') {
294
293
  continue;
@@ -303,7 +302,7 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
303
302
  labelContentEnd--;
304
303
  }
305
304
  if (labelContentEnd - labelStart > Constants.MAX_URL_HOSTNAME_LABEL_LENGTH || labelContentEnd - hostnameStart > Constants.MAX_URL_HOSTNAME_LENGTH) {
306
- return { isValid: false, validHostnamePrefixEnd: validKnownTldPrefixEnd };
305
+ return { isValid: false };
307
306
  }
308
307
  // Protocol URLs can end at any valid label; bare URLs still need a known TLD.
309
308
  if (hasProtocol) {
@@ -312,13 +311,10 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
312
311
  if (validLabelEnd !== index) {
313
312
  return { isValid: false, validHostnamePrefixEnd };
314
313
  }
315
- if (index !== hostnameContentEnd) {
314
+ if (!hasProtocol && index !== hostnameContentEnd) {
316
315
  const tldEnd = findKnownTldEnd(text, index);
317
316
  if (tldEnd !== undefined && tldEnd <= hostnameContentEnd && tldEnd - hostnameStart <= Constants.MAX_URL_HOSTNAME_LENGTH) {
318
- validKnownTldPrefixEnd = tldEnd;
319
- if (!hasProtocol) {
320
- validHostnamePrefixEnd = tldEnd;
321
- }
317
+ validHostnamePrefixEnd = tldEnd;
322
318
  }
323
319
  }
324
320
  labelStart = index + 1;
@@ -1782,21 +1778,20 @@ class ExpensiMark {
1782
1778
  const invalidUrlRanges = shouldRejectPartialHostnameMatches ? findInvalidUrlRanges(textWithContext) : [];
1783
1779
  const maskedText = invalidUrlRanges.length > 0 ? maskInvalidUrlRanges(textWithContext, invalidUrlRanges) : textWithContext;
1784
1780
  const textToMatch = maskedText.slice(0, textToCheck.length);
1785
- const contextRegex = followingText ? new RegExp(regex.source, regex.flags.replace('g', 'y')) : undefined;
1781
+ const contextRegex = followingText || invalidUrlRanges.length > 0 ? new RegExp(regex.source, regex.flags.replace('g', 'y')) : undefined;
1786
1782
  let match = matchingRegex.exec(textToMatch);
1787
1783
  let replacedText = '';
1788
1784
  let startIndex = 0;
1789
1785
  while (match !== null) {
1790
- if (contextRegex && match.index + match[0].length === textToCheck.length) {
1791
- // Recheck only this match with its following text, without searching outside the candidate.
1786
+ const matchEnd = match.index + match[0].length;
1787
+ if (contextRegex && (textWithContext[matchEnd] === '@' || (followingText.length > 0 && matchEnd === textToCheck.length))) {
1788
+ // Check the original context so masking cannot turn an email's local part into a URL.
1792
1789
  contextRegex.lastIndex = match.index;
1793
- const contextMatch = contextRegex.exec(maskedText);
1794
- if (contextMatch === null) {
1790
+ const contextMatch = contextRegex.exec(textWithContext);
1791
+ if (contextMatch === null || contextMatch[0].length < match[0].length) {
1795
1792
  match = matchingRegex.exec(textToMatch);
1796
1793
  continue;
1797
1794
  }
1798
- match = contextMatch;
1799
- matchingRegex.lastIndex = contextRegex.lastIndex;
1800
1795
  }
1801
1796
  let url = match[2];
1802
1797
  const urlEnd = findUrlEndBeforeUnmatchedParenthesis(url, 0, url.length);
package/dist/esm/API.js CHANGED
@@ -241,16 +241,6 @@ export default function API(network, args) {
241
241
  const newParameters = Object.assign(Object.assign({}, parameters), { api_setCookie: false });
242
242
  return performPOSTRequest(commandName, newParameters);
243
243
  },
244
- /**
245
- * @param {Object} parameters
246
- * @param {String} parameters.email
247
- * @returns {ExpensifyAPIDeferred}
248
- */
249
- Domain_RequestAccess(parameters) {
250
- const commandName = 'Domain_RequestAccess';
251
- requireParameters(['email'], parameters, commandName);
252
- return performPOSTRequest(commandName, parameters);
253
- },
254
244
  /**
255
245
  * @param {Object} parameters
256
246
  * @param {String[]} parameters.emailList
@@ -231,14 +231,14 @@ function findKnownTldEnd(text, dotPosition) {
231
231
  return undefined;
232
232
  }
233
233
  /**
234
- * Validates a hostname and records a linkable prefix before a later malformed label.
235
- * Preserves known-TLD prefixes before oversized continuations without recovering text inside an invalid leading label.
234
+ * Validates a hostname and records a linkable prefix before malformed punctuation in a later label.
235
+ * Rejects the whole hostname when a label or its complete length exceeds a DNS limit.
236
236
  *
237
237
  * @param text - Text containing the URL candidate.
238
238
  * @param hostnameStart - Index of the hostname's first character.
239
239
  * @param hostnameEnd - Index immediately after the hostname.
240
240
  * @param hasProtocol - Whether the URL allows hostnames without a known TLD, including single-label hosts.
241
- * @returns The hostname validity and any prefix that can be linked before a malformed or oversized continuation.
241
+ * @returns The hostname validity and any prefix that can be linked before malformed punctuation.
242
242
  */
243
243
  function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
244
244
  let hostnameContentEnd = hostnameEnd;
@@ -250,7 +250,6 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
250
250
  }
251
251
  let labelStart = hostnameStart;
252
252
  let validHostnamePrefixEnd;
253
- let validKnownTldPrefixEnd;
254
253
  for (let index = hostnameStart; index <= hostnameContentEnd; index++) {
255
254
  if (index !== hostnameContentEnd && text[index] !== '.') {
256
255
  continue;
@@ -265,7 +264,7 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
265
264
  labelContentEnd--;
266
265
  }
267
266
  if (labelContentEnd - labelStart > Constants.MAX_URL_HOSTNAME_LABEL_LENGTH || labelContentEnd - hostnameStart > Constants.MAX_URL_HOSTNAME_LENGTH) {
268
- return { isValid: false, validHostnamePrefixEnd: validKnownTldPrefixEnd };
267
+ return { isValid: false };
269
268
  }
270
269
  // Protocol URLs can end at any valid label; bare URLs still need a known TLD.
271
270
  if (hasProtocol) {
@@ -274,13 +273,10 @@ function analyzeHostname(text, hostnameStart, hostnameEnd, hasProtocol) {
274
273
  if (validLabelEnd !== index) {
275
274
  return { isValid: false, validHostnamePrefixEnd };
276
275
  }
277
- if (index !== hostnameContentEnd) {
276
+ if (!hasProtocol && index !== hostnameContentEnd) {
278
277
  const tldEnd = findKnownTldEnd(text, index);
279
278
  if (tldEnd !== undefined && tldEnd <= hostnameContentEnd && tldEnd - hostnameStart <= Constants.MAX_URL_HOSTNAME_LENGTH) {
280
- validKnownTldPrefixEnd = tldEnd;
281
- if (!hasProtocol) {
282
- validHostnamePrefixEnd = tldEnd;
283
- }
279
+ validHostnamePrefixEnd = tldEnd;
284
280
  }
285
281
  }
286
282
  labelStart = index + 1;
@@ -1744,21 +1740,20 @@ class ExpensiMark {
1744
1740
  const invalidUrlRanges = shouldRejectPartialHostnameMatches ? findInvalidUrlRanges(textWithContext) : [];
1745
1741
  const maskedText = invalidUrlRanges.length > 0 ? maskInvalidUrlRanges(textWithContext, invalidUrlRanges) : textWithContext;
1746
1742
  const textToMatch = maskedText.slice(0, textToCheck.length);
1747
- const contextRegex = followingText ? new RegExp(regex.source, regex.flags.replace('g', 'y')) : undefined;
1743
+ const contextRegex = followingText || invalidUrlRanges.length > 0 ? new RegExp(regex.source, regex.flags.replace('g', 'y')) : undefined;
1748
1744
  let match = matchingRegex.exec(textToMatch);
1749
1745
  let replacedText = '';
1750
1746
  let startIndex = 0;
1751
1747
  while (match !== null) {
1752
- if (contextRegex && match.index + match[0].length === textToCheck.length) {
1753
- // Recheck only this match with its following text, without searching outside the candidate.
1748
+ const matchEnd = match.index + match[0].length;
1749
+ if (contextRegex && (textWithContext[matchEnd] === '@' || (followingText.length > 0 && matchEnd === textToCheck.length))) {
1750
+ // Check the original context so masking cannot turn an email's local part into a URL.
1754
1751
  contextRegex.lastIndex = match.index;
1755
- const contextMatch = contextRegex.exec(maskedText);
1756
- if (contextMatch === null) {
1752
+ const contextMatch = contextRegex.exec(textWithContext);
1753
+ if (contextMatch === null || contextMatch[0].length < match[0].length) {
1757
1754
  match = matchingRegex.exec(textToMatch);
1758
1755
  continue;
1759
1756
  }
1760
- match = contextMatch;
1761
- matchingRegex.lastIndex = contextRegex.lastIndex;
1762
1757
  }
1763
1758
  let url = match[2];
1764
1759
  const urlEnd = findUrlEndBeforeUnmatchedParenthesis(url, 0, url.length);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expensify-common",
3
- "version": "2.0.223",
3
+ "version": "2.0.225",
4
4
  "author": "Expensify, Inc.",
5
5
  "description": "Expensify libraries and components shared across different repos",
6
6
  "homepage": "https://expensify.com",