JS: Regex Flag v (unicodeSets)
(new in ECMAScript 2024)
work in progressWhat's regex flag v
The v flag (unicodeSets) is an upgrade to the older u (unicode) flag for JavaScript regular expressions. It enables enhanced Unicode features.
when on, it features ALL capabilities of the u flag.
and:
Unicode properties of strings
\p{unicode_property} can match unicode properties of strings, such as emoji sequences with skin color modifiers, or nation's flags made of 2 code points, etc.
console.log("🇺🇳".match(/\p{RGI_Emoji_Flag_Sequence}/v)); // [ "🇺🇳", index: 0, input: "🇺🇳", groups: undefined ]
Set notation in character classes
Set notation in character classes: intersection (&&), union, and subtraction (--), plus nested classes and multi-code-point matches.
const xresult = "é Δ α β".matchAll(/[\p{Lowercase}&&\p{Script=Greek}]/gv); console.log(Array.from(xresult)); /* [ [ "α", index: 4, input: "é Δ α β", groups: undefined ], [ "β", index: 6, input: "é Δ α β", groups: undefined ] ] */
Cannot be used with flag u
flag u and v cannot be used together. only one of them. when both are used, it throws SyntaxError.
const rgx = /x/uv; // error: Uncaught SyntaxError: Invalid regular expression flags
Some patterns valid under u are invalid under v (stricter character class rules).
🟢 tip: flag v fixes lots classic regex problems, and added advanced features. It's good idea to always have it on, unless you have specific reason not to.
Example. intersection of unicode properties
// get lowercase Greek letters. const rgx = /[\p{Lowercase}&&\p{Script=Greek}]/gv; const xtext = "symbols à á â ⊕ Δ α β"; const xresult = xtext.matchAll(rgx); console.log( Array.from(xresult), ); /* [ [ "α", index: 18, input: "symbols à á â ⊕ Δ α β", groups: undefined ], [ "β", index: 20, input: "symbols à á â ⊕ Δ α β", groups: undefined ] ] */
Substraction of unicode character class sets
// Match any letter that is NOT ASCII (i.e. non-English letters) const rgx = /[\p{Letter}--\p{ASCII}]/gv; const xtext = "some á Δ α β"; const xresult = xtext.matchAll(rgx); console.log(Array.from(xresult)); /* [ [ "á", index: 5, input: "some á Δ α β", groups: undefined ], [ "Δ", index: 7, input: "some á Δ α β", groups: undefined ], [ "α", index: 9, input: "some á Δ α β", groups: undefined ], [ "β", index: 11, input: "some á Δ α β", groups: undefined ] ] */
Unicode string properties
in JavaScript regex v flag, what does this mean \p{...} can match properties of strings (not just single characters).
(ai answer)
With the v flag, \p{…} can match properties of strings (multi-code-point sequences), not only single characters.
This is mainly useful for emoji. Properties like these match complete sequences in one go:
RGI_EmojiRGI_Emoji_Flag_SequenceRGI_Emoji_ZWJ_SequenceEmoji_Keycap_Sequence- etc.
Example
// flag of united nations. made up of 2 code points. const xtext = "🇺🇳"; const rgx = /\p{RGI_Emoji_Flag_Sequence}/gv; const xresult = xtext.matchAll(rgx); console.log(Array.from(xresult)); // [ [ "🇺🇳", index: 0, input: "🇺🇳", groups: undefined ] ]
You do not need + for these string properties. The property itself already represents the full sequence.
Important distinctions
- Character properties (e.g.
\p{L},\p{Script=Greek}) still match one character at a time, even withv. You still need+/*if you want sequences of them. - This works both outside and inside character classes (
[...]). It is not limited to square brackets. \P{…}cannot be used with string properties (it would be ambiguous how many characters to consume).
So: the “no plus needed” behavior applies only to the special multi-code-point string properties, not to ordinary character properties.
is the 'multi-code-point string properties' concept from unicode spec?
Yes. The concept of properties of strings (including multi-code-point ones) comes from the Unicode Standard.
Unicode distinguishes:
- Character/code point properties (apply to single code points)
- Properties of strings (apply to sequences of one or more code points)
This is covered in:
- UTR #23 (The Unicode Character Property Model) — defines properties of strings and enumerated sets of strings.
- UTS #51 (Unicode Emoji) — explicitly defines the emoji-related ones (e.g.
RGI_Emoji,RGI_Emoji_Flag_Sequence,RGI_Emoji_ZWJ_Sequence, etc.) as binary properties of strings. These are the ones JavaScript’svflag currently supports.
So the multi-code-point behavior you see with \p{RGI_Emoji} etc. is not a JavaScript invention — it is directly based on Unicode’s definition of those string properties.
what's RGI_Emoji
RGI_Emoji = Recommended for General Interchange emoji.
It is a Unicode property of strings (defined in UTS #51) that matches the set of emoji characters and sequences that Unicode recommends for general use/interchange.
It includes:
- Single-code-point emoji (Basic_Emoji)
- Flag sequences (e.g. 🇺🇸)
- Skin-tone modifier sequences (e.g. 👋🏽)
- ZWJ sequences (e.g. 👨👩👧, 👨⚕️)
- Keycap sequences (e.g. 1️⃣)
- Tag sequences (e.g. 🏴)
In JavaScript with the v flag:
/\p{RGI_Emoji}/v
This matches complete emoji (whether one code point or many) in one match, which is usually what you want instead of the broader/older \p{Emoji} property.
Property regexp.prototype.unicodesets
const rgx = /some/v; console.assert(rgx.unicodeSets === true);