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 indicateurs Unicode (/u) et persistant (/y). Mais le développement ne s'est pas arrêté depuis. En collaboration avec d'autres membres de TC39 (organisme de normalisation ECMAScript), l'équipe V8 a proposé et co-conçu 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à à l'étape 3 du processus TC39. Nous avons mis en œuvre ces fonctionnalités derrière un drapeau (voir ci-dessous) afin de pouvoir fournir rapidement des commentaires sur la conception et la mise en œuvre aux auteurs respectifs des propositions avant que la spécification ne soit finalisée.

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

Captures nommées

Les expressions régulières peuvent contenir ce que l'on appelle des captures (ou groupes), qui peuvent capturer une partie du texte correspondant. Jusqu'à présent, les développeurs ne pouvaient faire référence à ces captures qu'à l'aide de leur index, 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'

Toutefois, les expressions régulières sont déjà connues pour être difficiles à lire, écrire et gérer, et les références numériques peuvent compliquer encore davantage la tâche. Par exemple, dans les modèles plus longs, il peut être difficile de déterminer l'index d'une capture particulière:

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

Pire encore, les modifications apportées à un modèle peuvent potentiellement décaler les index 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 permettra d'atténuer 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éférences arrière 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.

Indicateur dotAll

Par défaut, l'atome . dans les expressions régulières correspond à n'importe quel caractère, à l'exception des caractères de fin 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 caractères de fin 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 autres caractères peuvent être considérés comme des nombres (par exemple, le chiffre 1 dans un cercle : 1) ou des caractères qualificatifs (par exemple, le caractère chinois pour neige : 雪).

Aucune de ces options ne peut correspondre à \d ou \w. Si vous modifiez le sens de ces raccourcis, les modèles d'expressions régulières existants seraient rompus.

À 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 signalées par l'option /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 découvrir d'autres exemples, consultez cet article informatif.

Assertions rétrospectives

Les assertions avant font partie de la syntaxe d'expression régulière de JavaScript depuis le début. Leurs équivalents, les assertions "Look-Behind", sont enfin introduites. Certains d'entre vous se souviennent peut-être que cela fait déjà partie de V8 depuis un certain temps déjà. Nous utilisons même des assertions "Lookbehind" en arrière-plan pour implémenter l'indicateur Unicode spécifié dans ES2015.

Le nom décrit déjà plutôt bien sa signification. Il permet de restreindre un modèle à la correspondance uniquement s'il est précédé par le modèle du groupe d'apparences en arrière-plan. Il existe à la fois des types avec et sans correspondance:

/(?<=\$)\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 consacré aux assertions derrière les assertions ainsi que des exemples dans les scénarios de test V8 associés.

Remerciements

Cet article de blog ne serait pas complet sans mentionner certaines des personnes qui ont travaillé dur pour y parvenir: en particulier les champions de langue Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin et le expert Irregexp d'Erik Corry dans l'implémentation de ces fonctionnalités.

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