Source: app/data/regexPatterns.js

import { countryCode } from './enum/Countries'; // disable for the whole file
import ExcludeAlternateLink from './enum/ExcludeAlternateLink';
/**
 * Regex pattern matching last part of string not ending with a whitespace
 * @type {RegExp}
 * @example  "Name "
 */
export const NOT_WHITESPACE_END_REGEX = /[^\s]+$/;

/**
 * Regex pattern matching any amount of whitespace at the start of the string
 * @type {RegExp}
 * @example  " Name"
 */
export const NO_WHITESPACE_START_REGEX = /^\s*/g;

/**
 * Regex pattern matching any amount of whitespace at the start of the string
 * @type {RegExp}
 * @example  " Name "
 */
export const NO_WHITESPACE_START_AND_END_REGEX = /^[^\s]+(\s+[^\s]+)*$/i;

/**
 * Regex pattern matching any whitespace within the string
 * @type {RegExp}
 */
export const MATCH_WHITESPACE = /[\s]/g;

/**
 * Regex pattern matching fragment starting with an @ followed by zero
 * or more alphanumeric characters
 * @type {RegExp}
 * @example @person
 */
export const TAG_REGEX = /(?!\b)@[a-z0-9._]*/i;

/**
 * Regex for base64 value
 * @type {RegExp}
 */
export const BASE_64_REGEX = /^data:image\/[a-z]+;base64,/;

/**
 * Regex pattern that matches youtube video urls
 * @type {RegExp}
 */
export const YOUTUBE_REGEX = /(?:youtu\.be\/|youtube\.com\/(?:watch\?(?:.*&)?v=|(?:embed|v)\/))([^?&"'>]+)/;

/**
 * Regex pattern that matches paths/urls with an image extension at it's end
 * @type {RegExp}
 * @example awesome.gif
 */
export const IMAGE_REGEX = /\S+\.(gif|jpe?g|png)\b[-a-z0-9@:%_+.~#?&/=]*/i;

/**
 * The full link regex is needed, because we don't want to match uploaded image
 *
 * Regex pattern that matches internal category articles
 * @type {RegExp}
 */
export const INTERNAL_LINK = /(https?:\/\/)?(dev-|acc-|tst-)?(www|member|public)\.slimmingworld\.com\/(recipes|features|community|success-stories)\/.+/i;

/**
 * Regex pattern to extract both post card parts from a string
 * @type {RegExp}
 * @example NG20OQQ
 */
export const EXTRACT_BOTH_PARTS_OF_UK_POSTCODE_REGEX = /^([A-Z]{1,2}[\dA-Z]{1,2})[ ]?(\d[A-Z]{2})$/i;

export const FIRST_POSTCODE_PART = /[A-Za-z]{1,2}[\d]/;

/**
 * A pattern that matches linebreaks from textarea elements
 * @type {RegExp}
 * @example \r\, \n
 */
export const LINE_BREAKS_REGEX = /(\r\n|\n|\r)/gm;

/**
 * A pattern to detect the last slash of an occurrence
 *  @type {RegExp}
 */
export const LAST_SLASH_OCCURRENCE_REGEX = /\/$/g;

/**
 * Convert minutes within a ISO 8601 duration string
 * @example PT1H10M would return 10
 */
export const DURATION_MINUTES = /[0-9]{1,2}(?=M)/;

/**
 * Convert hours within a ISO 8601 duration string
 * @example PT1H10M would return 1
 */
export const DURATION_HOURS = /[0-9]{1,2}(?=H)/;

/**
 * Only single digit value
 * @type {RegExp}
 */
export const ONLY_SINGLE_DIGITS = /^([1-9])$/;

/**
 * postal codes regex values
 * @type {RegExp}
 * @example GB: SW1 1EA
 * @example US: 12345
 * @example IE: IE1 1SW
 * @example CY: 1234
 */
export const POSTAL_CODES = {
  [countryCode.GB]: /^([A-PR-UWYZ][A-HK-Y0-9](?:[A-HJKS-UW0-9][ABEHMNPRV-Y0-9]?)?\s*[0-9][ABD-HJLNP-UW-Z]{2}|GIR\s*0AA)$/i,
  [countryCode.US]: /^\d{5}(?:[-\s]\d{4})?$/i,
  [countryCode.IRELAND]: /(?:^[AC-FHKNPRTV-Y][0-9]{2}|D6W)[ -]?[0-9AC-FHKNPRTV-Y]{4}$/i,
  [countryCode.CYPRUS]: /^\d{4}$/i,
};

/**
 * Phone number regex object
 * @type {RegExp}
 * @example GB - 01234 567 890,
 * @example US - 012 345 6789,
 * @example IE - 012 3456789
 * @example CY - 01 234567,
 */
export const PHONE_NUMBER_REGEX = {
  [countryCode.GB]: /^0(?:1|2|7)(?:\d{3}\s?\d{3}\s?\d{3})/i,
  [countryCode.US]: /^(\d{3}\s\d{3}\s\d{4})/i,
  [countryCode.IRELAND]: /^(\d{3}\s\d{7})/i,
  [countryCode.CYPRUS]: /^(\d{2}\s\d{6})/i,
};

export const PHONE_NUMBER_MASK = {
  [countryCode.GB]: [/\d/, /\d/, /\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/],
  [countryCode.US]: [/\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, /\d/],
  [countryCode.IRELAND]: [/\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, /\d/, /\d/, /\d/, /\d/],
  [countryCode.CYPRUS]: [/\d/, /\d/, ' ', /\d/, /\d/, /\d/, /\d/, /\d/, /\d/],
};

/**
 * password strength - Must be 8-64 characters & have at least one number
 * @type {RegExp}
 * @example daverock123
 * A pattern to detect the password
 * at least 1 letter
 * at least 1 digit
 * between 6 to 64 characters
 */
export const PASSWORD_REGEX = /(^(?=.*\d)(?=.*[a-z]).{8,64}$)/i;
export const PASSWORD_DIGIT_REGEX = /(?=.*\d)/;
export const PASSWORD_LETTER_REGEX = /(?=.*[a-z-A-Z])/;
export const PASSWORD_MIN_MAX_REGEX = /^.{8,64}$/;

/**
 * Regex pattern matching the section of url after the last slash
 * @type {RegExp}
 * @example  "recipe/breakfast/fry-up" would match "fry"
 */
export const URL_AFTER_LAST_SLASH_REGEX = /([^/]+$)/;

/**
 * Match non alphanumeric charachters (excluding whitespace)
 * @type {RegExp}
 * @example  "Hello! it's a me, mario" would match "!',"
 */
export const ONLY_ALPHANUMERIC = /[^a-zA-Z0-9\s-]/g;

/**
 * Checks if origin is part of url
 *
 * Following urls match with this pattern:
 * acc-origin-account.slimmingworld.co.uk
 * origin-account.slimmingworld.co.uk
 * http://acc-origin-account.slimmingworld.co.uk
 * https://acc-origin-account.slimmingworld.co.uk
 */
export const ORIGIN_DETECTION = /^(https?:\/\/)?([a-z]{3}-)?origin/i;

/**
 * Regex request path
 * @type {RegExp}
 * @example would match 'recipes/spiced-rice-pudding'
 * @example would not match 'recipes/spiced-rice-pudding-sql(test)'
 */
export const REQUEST_PATH_REGEX = /^[A-Za-z\-0-9/_=+]+(\?.*)?$/;

/**
 * Regex that pull the environment preifx from the url
 * @type {RegExp}
 * @example would match 'dev' from 'http://dev-www.swlabs.digital'
 */
export const MATCH_FIRST = /(^(.*)-www)/g;

/**
 * Regex matches hyphens in counties
 * @type {RegExp}
 * @example would match '-' from 'https://www.slimmingworld.co.uk/counties/south-yorkshire'
 */
export const MATCH_HYPHENS = /-/g;

const stringifyExcludedCanonical = ExcludeAlternateLink.reduce(
  (accumulator, currentValue, index) => {
    // Escape slashes on first item
    if (index === 1) {
      accumulator = accumulator.replace(/\//g, '\\/'); // eslint-disable-line no-param-reassign
    }

    // Escape slashes and remove params within urls e.g :id
    const stripParams = currentValue.replace(/\/:(.*)/g, '');
    accumulator = `${accumulator}|${stripParams}`; // eslint-disable-line no-param-reassign
    return accumulator;
  },
);

/**
 * Matches routes that do not need a alternate link see ExcludeAlternateLinks
 * for full list of routes excluded
 * @type {RegExp}
 * @example would match 'group' from 'https://www.slimmingworld.co.uk/group/354501'
 */
export const MATCH_EXCLUDE_ALTERNATE_LINK = new RegExp(stringifyExcludedCanonical, 'g');

/**
 * Match numeric only characters (excluding whitespace)
 * @type {RegExp}
 * @example  "2423424234234" would match "!',"
 */
export const ONLY_NUMERIC = /^\d+$/;

/**
 * Regex pattern matching a valid first name of somebody signing up to the newsletter
 * @type {RegExp}
 * @example  "Chloé" would match
 * @example  "www.slimmingworld.co.uk" would NOT match
 */
export const FIRSTNAME_EMAIL_SIGNUP_REGEX = /^[^@./]*$/;

/**
 * Only 6 digits allowed
 *
 * @type {RegExp}
 */
export const ONLY_SIX_NUMERIC = /^\d{6}$/;