Last active
July 11, 2024 18:03
-
-
Save lewxdev/9cdfe794d5dde3bab504b1bc394720ed to your computer and use it in GitHub Desktop.
a utility function `$p()` that creates regular expression patterns from shorthand
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Produces an array of locale-respective formats | |
* @template {keyof Intl.DateTimeFormatOptions} K | |
* @template {(NonNullable<Intl.DateTimeFormatOptions[K]>)[]} [F=["long", "short"]] | |
* @param {K} key - a valid key on the `Intl.DateTimeFormatOptions` object | |
* @param {number} quantity - the number of units of the provided option | |
* @param {(index: number) => Date} callback - used for creating subsequent dates | |
* @param {F} formats - an optional list of formats to generate and key | |
* @returns {{ [format in F[number]]: string }[]} | |
*/ | |
const $f = (key, quantity, callback, formats = ["long", "short"]) => | |
[...Array(quantity)].map((_, i) => | |
formats.reduce((result, format) => ({ | |
[format]: callback(i).toLocaleString("en", { [key]: format }), | |
...result | |
}), {}) | |
) | |
/** A reference to the locale-generated named months */ | |
const $M = $f("month", 12, (i) => new Date(0, i)) | |
/** A reference to the locale-generated named weekdays */ | |
const $D = $f("weekday", 7, (i) => new Date(0, 0, i)) | |
/** | |
* The shorthand string mapping to regular expression | |
* components/patterns (as strings) for use in the interface | |
*/ | |
const $S = { | |
// Currency patterns | |
/** Comma-separated values (e.g. "1,000.00") */ | |
C0_000_00: "(?<!\\.|,|\\d)(?:(?:(?:\\d{1,3},\\d{2})*|\\d{1,2})\\d\\.\\d{2})\\b", | |
/** Non comma-separated values (e.g. "1000.00") */ | |
C0000_00: "\\b\\d+\\.\\d{2}\\b", | |
// Readable date pattern components | |
/** @see {@link https://en.wikipedia.org/wiki/Date_format_by_country#Table_coding} */ | |
/** 4-digit year (e.g. "2020") */ | |
YYYY: "\\b\\d{4}\\b", | |
/** 2-digit year (e.g. 2020 as "20") */ | |
YY: "\\b\\d{2}\\b", | |
/** The fully named month (e.g. "November") */ | |
MMMM: `\\b${$M.map(({ long }) => long).join("|")}\\b`, | |
/** 3-letter, abbreviated named month (e.g. January as "Jan") */ | |
MMM: `\\b${$M.map(({ short }) => short).join("|")}\\b`, | |
/** 2-digit, zero-leading numeric month (e.g. April as "04") */ | |
MM: "\\b(?:0[1-9])|(?:1[0-2])\\b", | |
/** Non zero-loading numeric month (e.g. May as "5") */ | |
M: "\\b[1-9]|(?:1[0-2])\\b", | |
/** The fully named weekday (e.g. "Wednesday") */ | |
DDDD: `\\b${$D.map(({ long }) => long).join("|")}\\b`, | |
/** 3-letter, abbreviated named weekday (e.g. Friday as "Fri") */ | |
DDD: `\\b${$D.map(({ short }) => short).join("|")}\\b`, | |
/** 2-digit, zero-leading day (e.g. 09 February as "09") */ | |
DD: "\\b(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1])\\b", | |
/** Non zero-leading day (e.g. 7 December as "7") */ | |
D: "\\b[1-9]|(?:[1-2][0-9])|(?:3[0-1])\\b", | |
} | |
/** An expression that matches the keys for the interface shorthand patterns */ | |
const $P = new RegExp(Object.keys($S).join("|"), "g") | |
/** | |
* Dynamically converts shorthanded patterns from an input string to | |
* regular expression | |
* @param {string} input - the provided shorthanded string to convert | |
* @param {string=} flags - optional RegExp flags to create the expression with | |
* @returns - a regular expression object with named groups | |
* corresponding to the matched shorthand | |
* | |
* @example <caption>Date pattern</caption> | |
* // Equivalent pattern: | |
* /(?<YYYY>\b\d{4}\b)-(?<MM>\b(?:0[1-9])|(?:1[0-2])\b)-(?<DD>\b(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1])\b)/ | |
* | |
* "2020-01-01".match($p("YYYY-MM-DD")) | |
* | |
* @example <caption>Currency pattern</caption> | |
* // Equivalent pattern: | |
* /(?<C0_000_00>(?<!\.|,|\d)(?:(?:(?:\d{1,3},\d{2})*|\d{1,2})\d\.\d{2})\b)/ | |
* | |
* "1,749.99".match($p("C0_000_00")) | |
*/ | |
const $p = (input, flags) => | |
new RegExp(input.replace($P, (match) => `(?<${match}>${$S[match]})`), flags) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment