Comment modifier les nœuds dans une syntaxe abstraite
L'un des concepts les plus puissants sur lesquels j'ai tombé récemment est l'idée de syntaxes abstraits, ou AST. Si vous avez déjà étudié l'alchimie, vous vous souvenez peut-être que toute la motivation pour les alchimistes était de découvrir un moyen de transformer non pas en or par des méthodes scientifiques ou arcaniques.
Les asts sont un peu comme ça. En utilisant les AST, nous pouvons transformer Markdown en HTML, JSX en JavaScript, et bien plus encore.
Pourquoi les AST sont-ils utiles?
Au début de ma carrière, j'ai essayé de modifier des fichiers à l'aide d'une méthode de recherche-et-répétition. Cela a fini par être assez compliqué, j'ai donc essayé d'utiliser des expressions régulières. J'ai fini par abandonner l'idée parce qu'elle était si fragile; L'application s'est brisée tout le temps parce que quelqu'un entrait dans le texte d'une manière que je n'avais pas prévu et cela briserait mes expressions régulières provoquant la chute de l'ensemble de l'application.
La raison pour laquelle cela a été si difficile est que le HTML est flexible. Cela rend extrêmement difficile l'analyse en utilisant des expressions régulières. Un remplacement basé sur des cordes comme celui-ci est sujet à la rupture car il pourrait manquer un match, faire trop de match ou faire quelque chose de bizarre qui se traduit par un balisage invalide qui laisse la page Janky.
Les AST, en revanche, transforment HTML en quelque chose de bien plus structuré, ce qui rend beaucoup plus simple de plonger dans un nœud de texte et de faire des remplacements uniquement sur ce texte, ou de gâcher des éléments sans avoir à gérer le texte.
Cela rend la transformation AST plus sûre et moins sujet aux erreurs qu'une solution purement basée sur des chaînes.
À quoi servent les AST?
Pour commencer, jetons un coup d'œil à un document minimal en utilisant quelques lignes de marque. Ceci sera enregistré en tant que fichier appelé home.md, que nous allons enregistrer dans le dossier de contenu de notre site Web.
# Bonjour le monde! ! [Cardigan Corgi] (<https:>) Un adorable corgi! Un peu plus de texte va ici.</https:>
En supposant que nous connaissons Markdown, nous pouvons en déduire que lorsque cette marque est analysée, cela finira par être une balise H1 qui dit: "Bonjour le monde!" Ensuite, deux paragraphes de texte: le premier contient une image d'un corgi et du texte destiné à le décrire, et le second dit: "Un texte supplémentaire va ici."
Mais comment se transforme-t-il de Markdown en HTML?
C'est là que les Asts entrent!
Parce qu'il prend en charge plusieurs langues, nous allons utiliser la spécification de l'arborescence de syntaxe unist et, plus précisément, le projet unifié.
Installer les dépendances
Tout d'abord, nous devons installer les dépendances requises pour analyser la marque dans un AST et la convertir en HTML. Pour ce faire, nous devons nous assurer que nous avons initialisé le dossier en tant que package. Exécutez la commande suivante dans votre terminal:
# Assurez-vous que vous êtes dans votre dossier racine (où se trouve le «contenu») # Initialiser ce dossier en tant que package NPM npm init # Installez les dépendances NPM installer une remarque de remarque de remarque unifiée
Si nous supposons que notre marque est stocké dans Home.md, nous pouvons obtenir l'AST avec le code suivant:
const fs = require ('fs'); const Unified = require («unifié»); const markdown = require ('remarque-parse'); const html = require ('Remark-html'); const Contenu = Unified () .User (Markdown) .User (html) .processSync (fs.readfilesync (`$ {process.cwd ()} / contenu / home.md`)) .ToString (); console.log (contenu);
Ce code profite du module FS intégré de Node, qui nous permet d'accéder et de manipuler le système de fichiers. Pour plus d'informations sur le fonctionnement, consultez les documents officiels.
Si nous enregistrons cela en tant que src / index.js et utilisons le nœud pour exécuter ce script à partir de la ligne de commande, nous verrons ce qui suit dans notre terminal:
$ node src / index.js <h1 id="Bonjour-le-monde"> Bonjour le monde! </h1> <p> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi"> un adorable corgi! </p> <p> Un texte supplémentaire va ici. </p>
Nous disons à Unified d'utiliser Remark-Parse pour transformer le fichier de marque en un AST, puis pour utiliser Remark-HTML pour transformer l'AST de Markdown en HTML - ou, plus précisément, il le transforme en quelque chose appelé un VFile. L'utilisation de la méthode TOSTRING () transforme ce AST en une chaîne réelle de HTML que nous pouvons afficher dans le navigateur!
Grâce au travail acharné de la communauté open source, Remark fait tout le travail acharné de transformer la marque en HTML pour nous. (Voir le diff)
Ensuite, regardons comment cela fonctionne réellement.
À quoi ressemble un AST?
Pour voir l'AST réel, écrivons un minuscule plugin pour le enregistrer:
const fs = require ('fs'); const Unified = require («unifié»); const markdown = require ('remarque-parse'); const html = require ('Remark-html'); const Contenu = Unified () .User (Markdown) .Use (() => arbre => console.log (JSON.Strinify (arbre, null, 2)))) .User (html) .processSync (fs.readfilesync (`$ {process.cwd ()} / contenu / home.md`)) .ToString ();
La sortie de l'exécution du script sera désormais:
{ "type": "racine", "enfants": [ { "Type": "En-tête", "profondeur": 1, "enfants": [ { "type": "texte", "Valeur": "Hello World!", "position": {} } ], "position": {} }, { "type": "paragraphe", "enfants": [ { "type": "image", "Titre": null, "URL": "<https:>", "Alt": "Cardigan Corgi", "position": {} }, { "type": "texte", "valeur": "un adorable corgi!", "position": {} } ], "position": {} }, { "type": "paragraphe", "enfants": [ { "type": "texte", "Valeur": "Un texte supplémentaire va ici.", "position": {} } ], "position": {} } ], "position": {} }</https:>
Notez que les valeurs de position ont été tronquées pour économiser de l'espace. Ils contiennent des informations sur l'endroit où se trouve le nœud dans le document. Aux fins de ce tutoriel, nous n'utiliserons pas ces informations. (Voir le diff)
C'est un peu écrasant à regarder, mais si nous zoomez, nous pouvons voir que chaque partie de la marque devient un type de nœud avec un nœud de texte à l'intérieur.
Par exemple, le titre devient:
{ "Type": "En-tête", "profondeur": 1, "enfants": [ { "type": "texte", "Valeur": "Hello World!", "position": {} } ], "position": {} }
Voici ce que cela signifie:
- Le type nous dit à quel type de nœud nous avons affaire.
- Chaque type de nœud a des propriétés supplémentaires qui décrivent le nœud. La propriété de profondeur sur le cap nous indique quel niveau de niveau est - une profondeur de 1 signifie que c'est une balise
, 2 signifie
, etc.
- Le tableau des enfants nous dit ce qu'il y a à l'intérieur de ce nœud. Dans le titre et le paragraphe, il n'y a que du texte, mais nous avons également pu voir des éléments en ligne ici, comme .
C'est la puissance des AST: nous avons maintenant décrit le document Markdown comme un objet qu'un ordinateur peut comprendre. Si nous voulons imprimer cela à Markdown, un compilateur de Markdown saurait qu'un nœud «en tête» avec une profondeur de 1 commence par #, et un nœud de texte enfant avec la valeur «bonjour» signifie que la ligne finale devrait être # bonjour.
Comment fonctionnent les transformations AST
La transformation d'un AST se fait généralement en utilisant le motif du visiteur. Il n'est pas important de connaître les tenants et les aboutissants de la façon dont cela fonctionne pour être productif, mais si vous êtes curieux, les modèles de conception JavaScript pour les humains de Soham Kamani ont un excellent exemple pour aider à expliquer comment cela fonctionne. La chose importante à savoir est que la majorité des ressources sur le travail AST parlera de «Visiter Nœuds», ce qui se traduit à peu près par «trouver une partie de l'AST afin que nous puissions faire des choses avec.» La façon dont cela fonctionne est que nous écrivons une fonction qui sera appliquée aux nœuds AST correspondant à nos critères.
Quelques notes importantes sur son fonctionnement:
- Les AST peuvent être énormes, donc pour des raisons de performance, nous muterons directement les nœuds. Cela va à l'encontre de la façon dont j'approcherais généralement les choses - en règle générale, je n'aime pas muter l'état mondial - mais cela a du sens dans ce contexte.
- Les visiteurs travaillent récursivement. Cela signifie que si nous traitons un nœud et créons un nouveau nœud du même type, le visiteur s'exécutera également sur le nœud nouvellement créé, sauf si nous ne disons pas explicitement au visiteur de ne pas le faire.
- Nous n'allons pas trop profondément dans ce tutoriel, mais ces deux idées nous aideront à comprendre ce qui se passe alors que nous commençons à jouer avec le code.
Comment modifier la sortie HTML de l'AST?
Et si nous voulons modifier la sortie de notre Markdown, cependant? Disons que notre objectif est d'envelopper des étiquettes d'image avec un élément de figure et de fournir une légende, comme ceci:
<figure> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi"> <figcaption> Un adorable corgi! figure></figcaption></figure>
Pour ce faire, nous aurons besoin de transformer le HTML AST - pas le Markdown AST - car Markdown n'a pas un moyen de créer des éléments de figure ou de figure. Heureusement, comme Unified est interopérable avec plusieurs analyseurs, nous pouvons le faire sans écrire un tas de code personnalisé.
Convertir une marque AST en un HTML AST
Pour convertir le Markdown AST en un HTML AST, ajoutez Remark-Rehype et passez à Richype-Strinify pour transformer l'AST en HTML.
NPM Installer Remark-Rehype Rehype-Stringify
Faire les modifications suivantes dans Src / index.js pour passer à RECHYPE:
const fs = require ('fs'); const Unified = require («unifié»); const markdown = require ('remarque-parse'); const remarqu2rehype = require ('Remark-rehype'); const html = require («rehype-stringify»); const Contenu = Unified () .User (Markdown) .User (Remark2reHype) .Use (() => arbre => console.log (JSON.Strinify (arbre, null, 2)))) .User (html) .ProcessSync (fs.readfilesync ('corgi.md')) .ToString (); console.log (contenu);
Notez que la variable HTML est passée de Remark-HTML à Rehype-Stringify - les deux transforment l'AST en un format qui peut être chaîné en HTML
Si nous exécutons le script, nous pouvons voir que l'élément d'image ressemble maintenant à ceci dans l'AST:
{ "type": "élément", "tagname": "img", "propriétés": { "src": "https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg", "Alt": "Cardigan Corgi" }, "enfants": [], "position": {} }
Il s'agit de l'AST pour la représentation HTML de l'image, nous pouvons donc commencer à le changer pour utiliser l'élément de figure. (Voir le diff)
Écrivez un plugin pour unifié
Pour envelopper notre élément IMG avec un élément de figure, nous devons écrire un plugin. Dans Unified, des plugins sont ajoutés avec la méthode use (), qui accepte le plugin comme un premier argument et toutes les options comme deuxième argument:
.User (plugin, options)
Le code du plugin est une fonction (appelée «attacheur» dans le jargon unifié) qui reçoit l'option. Ces options sont utilisées pour créer une nouvelle fonction (appelée «transformateur») qui reçoit l'AST et fonctionne pour, euh, la transformer. Pour plus de détails sur les plugins, consultez la vue d'ensemble du plugin dans les documents unifiés.
La fonction qu'il renvoie recevra l'intégralité de l'AST comme argument, et il ne renvoie rien. (N'oubliez pas que les AST sont mutés à l'échelle mondiale.) Créez un nouveau fichier appelé img-to figure.js dans le même dossier que index.js, puis mettez ce qui suit à l'intérieur:
module.exports = options => arbre => { console.log (arbre); };
Pour l'utiliser, nous devons l'ajouter à src / index.js:
const fs = require ('fs'); const Unified = require («unifié»); const markdown = require ('remarque-parse'); const remarqu2rehype = require ('Remark-rehype'); const html = require («rehype-stringify»); const imgtofigure = requis ('./ img-to figure'); const Contenu = Unified () .User (Markdown) .User (Remark2reHype) .User (imgtofigure) .ProcessSync (fs.readfilesync ('corgi.md')) .ToString (); console.log (contenu);
Si nous exécutons le script, nous verrons toute l'arbre déconnecté dans la console:
{ Type: «Root», enfants: [ { Type: «élément», Tagname: 'P', propriétés: {}, Enfants: [Array], position: [objet] }, {type: 'text', valeur: '\\ n'}, { Type: «élément», Tagname: 'P', propriétés: {}, Enfants: [Array], position: [objet] } ], position: { Démarrer: {ligne: 1, colonne: 1, décalage: 0}, fin: {ligne: 4, colonne: 1, décalage: 129} } }
(Voir le diff)
Ajouter un visiteur au plugin
Ensuite, nous devons ajouter un visiteur. Cela nous permettra réellement d'obtenir le code. Unified profite d'un certain nombre de packages d'utilité, tous préfixés avec unist-util- *, qui nous permettent de faire des choses courantes avec notre AST sans écrire de code personnalisé.
Nous pouvons utiliser unist-util-visit pour modifier les nœuds. Cela nous donne une aide à visiter qui prend trois arguments:
- Toute l'AST avec laquelle nous travaillons
- Une fonction de prédicat pour identifier les nœuds que nous voulons visiter
- Une fonction pour apporter des modifications à l'AST que nous voulons apporter
Pour installer, exécutez ce qui suit dans votre ligne de commande:
NPM Installer UniT-Util-Visit
Implémentez un visiteur dans notre plugin en ajoutant le code suivant:
const Visit = require («unist-util-visit»); module.exports = options => arbre => { visite( arbre, // Visitez uniquement des balises P contenant un élément IMG node => node.tagname === 'p' && node.children.some (n => n.tagname === 'img'), node => { console.log (nœud); } )); };
Lorsque nous exécutons ceci, nous pouvons voir qu'il n'y a qu'un seul nœud de paragraphe enregistré:
{ Type: «élément», Tagname: 'P', propriétés: {}, enfants: [ { Type: «élément», Tagname: «img», Propriétés: [Objet], enfants: [], position: [objet] }, {Type: 'Text', Valeur: 'Un adorable corgi!', Position: [Object]} ], position: { Démarrer: {ligne: 3, colonne: 1, décalage: 16}, fin: {ligne: 3, colonne: 102, décalage: 117} } }
Parfait! Nous obtenons uniquement le nœud de paragraphe qui a l'image que nous voulons modifier. Maintenant, nous pouvons commencer à transformer l'AST!
(Voir le diff)
Enveloppez l'image dans un élément figuré
Maintenant que nous avons les attributs d'image, nous pouvons commencer à changer l'AST. N'oubliez pas que les AST peuvent être vraiment grands, nous les mutés en place pour éviter de créer beaucoup de copies et potentiellement ralentir notre script.
Nous commençons par modifier le nom de tagNon du nœud pour être une figure au lieu d'un paragraphe. Le reste des détails peut rester le même pour le moment.
Apportez les modifications suivantes dans SRC / IMG-TO-FIGURE.JS:
const Visit = require («unist-util-visit»); module.exports = options => arbre => { visite( arbre, // Visitez uniquement des balises P contenant un élément IMG node => node.tagname === 'p' && node.children.some (n => n.tagname === 'img'), node => { node.tagname = 'figure'; } )); };
Si nous exécutons à nouveau notre script et regardons la sortie, nous pouvons voir que nous nous rapprochons!
<h1 id="Bonjour-le-monde"> Bonjour le monde! </h1> <gigne> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi"> un adorable corgi! figure> <p> Un texte supplémentaire va ici. </p></gigne>
(Voir le diff)
Utilisez le texte à côté de l'image comme une légende
Pour éviter de devoir écrire une syntaxe personnalisée, nous allons utiliser tout texte passé en ligne avec une image comme légende d'image.
Nous pouvons faire l'hypothèse selon laquelle généralement les images n'ont pas de texte en ligne dans Markdown, mais il convient de noter que cela pourrait faire apparaître à 100% des légendes involontaires pour les personnes qui écrivent Markdown. Nous allons prendre ce risque dans ce tutoriel. Si vous prévoyez de mettre cela en production, assurez-vous de peser les compromis et de choisir ce qui est le mieux pour votre situation.
Pour utiliser le texte, nous allons chercher un nœud de texte à l'intérieur de notre nœud parent. Si nous en trouvons un, nous voulons saisir sa valeur comme légende. Si aucune légende n'est trouvée, nous ne voulons pas du tout transformer ce nœud, afin que nous puissions revenir tôt.
Apportez les modifications suivantes à Src / img-to-figure.js pour saisir la légende:
const Visit = require («unist-util-visit»); module.exports = options => arbre => { visite( arbre, // Visitez uniquement des balises P contenant un élément IMG node => node.tagname === 'p' && node.children.some (n => n.tagname === 'img'), node => { // Trouvez le nœud de texte const textNode = node.children.find (n => n.type === 'text'); // S'il n'y a pas de légende, nous n'avons pas besoin de transformer le nœud if (! textNode) return; const Lynchage = textNode.value.trim (); console.log ({légende}); node.tagname = 'figure'; } )); };
Exécutez le script et nous pouvons voir la légende enregistrée:
{Légende: "Un adorable corgi!" }
(Voir le diff)
Ajoutez un élément Figcaption à la figure
Maintenant que nous avons notre texte de légende, nous pouvons ajouter une figure pour l'afficher. Nous pourrions le faire en créant un nouveau nœud et en supprimant l'ancien nœud de texte, mais comme nous mutons en place, il est un peu moins compliqué de simplement changer le nœud de texte en un élément.
Les éléments n'ont cependant pas de texte, nous devons donc ajouter un nouveau nœud de texte en tant qu'enfant de l'élément FigCaption pour afficher le texte de la légende.
Faire les modifications suivantes à Src / IMG-To-Figure.js pour ajouter la légende au balisage:
const Visit = require («unist-util-visit»); module.exports = options => arbre => { visite( arbre, // Visitez uniquement des balises P contenant un élément IMG node => node.tagname === 'p' && node.children.some (n => n.tagname === 'img'), node => { // Trouvez le nœud de texte const textNode = node.children.find (n => n.type === 'text'); // S'il n'y a pas de légende, nous n'avons pas besoin de transformer le nœud if (! textNode) return; const Lynchage = textNode.value.trim (); // modifie le nœud de texte en un élément FigCaption contenant un nœud de texte textNode.type = 'élément'; textNode.tagname = 'figCaption'; textNode.children = [ { Type: «Texte», Valeur: Légende } ]] node.tagname = 'figure'; } )); };
Si nous exécutons à nouveau le script avec le nœud src / index.js, nous voyons l'image transformée enveloppée dans un élément de figure et décrite avec une FigCaption!
<h1 id="Bonjour-le-monde"> Bonjour le monde! </h1> <figure> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="Cardigan corgi"> <figcaption> Un adorable corgi! Figcaption> Figure> <p> Un texte supplémentaire va ici. </p></figcaption></figure>
(Voir le diff)
Enregistrer le contenu transformé en un nouveau fichier
Maintenant que nous avons fait un tas de transformations, nous voulons enregistrer ces ajustements à un fichier réel afin que nous puissions les partager.
Étant donné que le Markdown n'inclut pas un document HTML complet, nous allons ajouter un autre plugin de réchype appelé Rehype-Document pour ajouter la structure du document complète et une balise de titre.
Installer en fonctionnant:
NPM Installer un document de réchype
Ensuite, apportez les modifications suivantes à src / index.js:
const fs = require ('fs'); const Unified = require («unifié»); const markdown = require ('remarque-parse'); const remarqu2rehype = require ('Remark-rehype'); const doc = require («rype-document»); const html = require («rehype-stringify»); const imgtofigure = requis ('./ img-to figure'); const Contenu = Unified () .User (Markdown) .User (Remark2reHype) .User (imgtofigure) .Use (Doc, {Titre: 'Un document transformé!'}) .User (html) .processSync (fs.readfilesync (`$ {process.cwd ()} / contenu / home.md`)) .ToString (); const OutputDir = `$ {process.cwd ()} / public`; if (! fs.existSync (outputDir)) { fs.mkDiRSync (outputDir); } fs.writeFileSync (`$ {outputDir} / home.html`, contenu);
Exécutez à nouveau le script et nous pourrons voir un nouveau dossier dans Root appelé public, et à l'intérieur, nous verrons Home.html. À l'intérieur, notre document transformé est enregistré!
<adal> <meta charset="utf-8"> <title> Un document transformé! <meta name="Viewport" content="width = Device-width, initial-scale = 1"> head> </title> <h1 id="Bonjour-le-monde"> Bonjour le monde! </h1> <figure> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="Cardigan corgi"> <figcaption> Un adorable corgi! Figcaption> Figure> <p> Un texte supplémentaire va ici. </p> </figcaption></figure></adal>
(Voir le diff)
Si nous ouvrons public / home.html dans un navigateur, nous pouvons voir notre marque transformée rendue comme une figure avec une légende.
Seaux saints! Regardez cet adorable corgi! Et nous savons que c'est adorable parce que la légende nous le dit.
Que faire ensuite
La transformation des fichiers à l'aide d'AST est extrêmement puissante - avec elle, nous pouvons créer à peu près tout ce que nous pouvons imaginer de manière sûre. Aucun regex fois ou analyse de chaîne requis!
De là, vous pouvez approfondir l'écosystème des plugins pour Remark and Rehype pour voir plus de ce qui est possible et obtenir plus d'idées pour ce que vous pouvez faire avec la transformation AST, de la création de votre propre générateur de sites statiques alimenté par Markdown; pour automatiser les améliorations des performances en modifiant le code en place; à tout ce que vous pouvez imaginer!
La transformation AST est une superpuissance codante. Commencez par vérifier le code source de cette démo - j'ai hâte de voir ce que vous construisez avec! Partagez vos projets avec moi sur Twitter.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Il est sorti! Félicitations à l'équipe Vue pour l'avoir fait, je sais que ce fut un effort massif et une longue période à venir. Tous les nouveaux documents aussi.

J'ai eu quelqu'un qui écrivait avec cette question très légitime. Lea vient de bloguer sur la façon dont vous pouvez obtenir les propriétés CSS valides elles-mêmes du navigateur. C'est comme ça.

Je dirais que "Site Web" correspond mieux que "Application mobile" mais j'aime ce cadrage de Max Lynch:

L'autre jour, j'ai repéré ce morceau particulièrement charmant sur le site Web de Corey Ginnivan où une collection de cartes se cassent les uns sur les autres pendant que vous faites défiler.

Si nous devons afficher la documentation à l'utilisateur directement dans l'éditeur WordPress, quelle est la meilleure façon de le faire?

Il existe un certain nombre de ces applications de bureau où l'objectif montre votre site à différentes dimensions en même temps. Vous pouvez donc, par exemple, écrire

CSS Grid est une collection de propriétés conçues pour faciliter la mise en page qu'elle ne l'a jamais été. Comme tout, il y a un peu une courbe d'apprentissage, mais Grid est

Je vois que Google Fonts a déployé un nouveau design (tweet). Comparé à la dernière grande refonte, cela semble beaucoup plus itératif. Je peux à peine faire la différence
