Fonctionnalités à venir pour les expressions régulières

ES2015 a introduit de nombreuses nouvelles fonctionnalités dans le langage JavaScript, y compris des améliorations significatives de la syntaxe des expressions régulières avec les options Unicode (/u) et persistantes (/y). Mais le développement n'a pas cessé depuis. En étroite collaboration avec d'autres membres de TC39 (l'organisme de normalisation ECMAScript), l'équipe V8 a proposé et co-créé plusieurs nouvelles fonctionnalités pour rendre les expressions régulières encore plus puissantes.

Ces fonctionnalités sont actuellement proposées pour être incluses dans la spécification JavaScript. Même si les propositions n'ont pas été entièrement acceptées, elles en sont déjà à la phase 3 du processus TC39. Nous avons implémenté ces fonctionnalités derrière un indicateur (voir ci-dessous) afin de pouvoir fournir des commentaires opportuns sur la conception et l'implémentation aux auteurs respectifs de la proposition avant que les spécifications ne soient finalisées.

Cet article de blog vous donne un aperçu de cet avenir passionnant. Si vous souhaitez suivre les exemples à venir, activez les fonctionnalités JavaScript expérimentales sur chrome://flags/#enable-javascript-harmony.

Captures nommées

Les expressions régulières peuvent contenir des "captures" (ou groupes), qui peuvent capturer une partie du texte correspondant. Jusqu'à présent, les développeurs ne pouvaient se référer à ces captures que par leur indice, qui est déterminé par la position de la capture dans le modèle.

const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'

Cependant, les expressions régulières sont déjà réputées difficiles à lire, à écrire et à gérer, et les références numériques peuvent ajouter d'autres complications. Par exemple, dans les modèles plus longs, il peut être difficile de déterminer l'indice d'une capture particulière:

/(?:(.)(.(?<=[^(])(.)))/  // Index of the last capture?

Pire encore, les modifications apportées à un modèle peuvent potentiellement modifier les indices de toutes les captures existantes:

/(a)(b)(c)\3\2\1/     // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/  // All need to be updated.

Les captures nommées sont une fonctionnalité à venir qui permet de limiter ces problèmes en permettant aux développeurs d'attribuer des noms aux captures. La syntaxe est semblable à celle de Perl, Java, .Net et Ruby:

const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'

Les captures nommées peuvent également être référencées par des rétroréférences nommées et via String.prototype.replace:

// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx');  // true

// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>');                              // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd);  // 'ba'

Pour en savoir plus sur cette nouvelle fonctionnalité, consultez la proposition de spécifications.

Option dotAll

Par défaut, l'atome . dans les expressions régulières correspond à n'importe quel caractère, à l'exception des terminateurs de ligne:

/foo.bar/u.test('foo\nbar');   // false

Une proposition introduit le mode dotAll, activé via l'indicateur /s. En mode dotAll, . correspond également aux terminateurs de ligne.

/foo.bar/su.test('foo\nbar');  // true

Pour en savoir plus sur cette nouvelle fonctionnalité, consultez la proposition de spécifications.

Échappements de propriété Unicode

Avec la prise en charge d'Unicode introduite dans ES2015, de nombreux caractères peuvent être considérés comme des chiffres, par exemple le chiffre 1 encerclé : ①, ou comme des caractères de mot, par exemple le caractère chinois pour la neige : 雪.

Aucun de ces éléments ne peut être associé à \d ou \w. Modifier la signification de ces abréviations endommagerait les modèles d'expression régulière existants.

À la place, de nouvelles séquences d'échappement de propriété sont introduites. Notez qu'ils ne sont disponibles que pour les expressions régulières compatibles avec Unicode, indiquées par l'indicateur /u.

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true

L'inverse peut être mis en correspondance avec \P.

/\P{Number}/u.test('①');      // false
/\P{Alphabetic}/u.test('雪');  // false

Le consortium Unicode définit de nombreuses autres propriétés, par exemple pour les symboles mathématiques ou les caractères hiragana japonais:

/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな');  // true

La liste complète des classes de propriétés Unicode compatibles est disponible dans la proposition de spécification actuelle. Pour en savoir plus, consultez cet article.

Assertions Lookbehind

Les assertions d'avance font partie de la syntaxe des expressions régulières JavaScript depuis le début. Leurs homologues, les assertions lookbehind, sont enfin introduites. Certains d'entre vous se souviennent peut-être que cela fait déjà partie de V8 depuis un certain temps. Nous utilisons même des assertions de prévisualisation sous le capot pour implémenter l'indicateur Unicode spécifié dans ES2015.

Le nom décrit déjà assez bien sa signification. Il permet de limiter une expression régulière à une correspondance uniquement si elle est précédée de l'expression du groupe d'analyse avant. Il existe des versions correspondantes et non correspondantes:

/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123');  // ['123']

Pour en savoir plus, consultez notre article de blog précédent dédié aux assertions lookbehind et les exemples dans les cas de test V8 associés.

Remerciements

Cet article de blog ne serait pas complet sans mentionner certaines des personnes qui ont travaillé dur pour que cela se produise, en particulier les champions du langage Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin et le gourou Irregexp Erik Corry, mais aussi toutes les autres personnes qui ont contribué à la spécification du langage et à l'implémentation de ces fonctionnalités dans V8.

Nous espérons que ces nouvelles fonctionnalités d'expression régulière vous plairont autant qu'à nous.