|
| 1 | +# Texte formatable |
| 2 | + |
| 3 | +```{danger} |
| 4 | +*Le texte formatable est un **sujet de travail actuel**. Son implémentation est susceptible de changer.* \ |
| 5 | +Par ailleurs, il est possible que cette fonctionnalité soit séparée dans un package nodejs indépendant. |
| 6 | +``` |
| 7 | + |
| 8 | +A certains endroits du site étu, les utilisateurs pourront formatter du texte. Nous avons décidé de nous baser sur une bibliothèque, [lexical](https://lexical.dev) ([github](https://github.com/facebook/lexical)). Bien que l'utilisateur puisse envoyer du contenu formatté sur à peu près n'importe quel champ texte de l'api (à condition de respecter la limite de caractères), il n'y a que quelques champs qui supportent réellement le texte formatté. |
| 9 | + |
| 10 | +```{warning} |
| 11 | +Les champs qui ne supportent pas le texte formatté acceptent **pour le moment** des inputs formattés. Cependant, ces champs ne seront pas traités comme telles par les applications front-end (comme le front du site étu). Cela peut donner lieu à un affichage considéré comme buggé si la feature est mal utilisée par certaines implémentations front-end ! |
| 12 | +``` |
| 13 | + |
| 14 | +## Abbréviations dans ce document |
| 15 | + |
| 16 | +Nous utiliserons dans ce documents les abbréviations/anglicismes suivantes : |
| 17 | + |
| 18 | +- RTE: Rich Text Editor, l'éditeur de texte dans lequel l'utilisateur peut formater du texte |
| 19 | +- Renderer: côté serveur, la fonction qui transforme du contenu lexical en html |
| 20 | +- Document Object Model (DOM): la structure d'un document, généralement HTML. On l'utilisera ici pour parler de tout ce qui est relatif à l'affichage du texte formatable. |
| 21 | + |
| 22 | +## Les bundles |
| 23 | + |
| 24 | +Un bundle est la définition de l'ensemble des contenus supportés par une zone de texte formatable. Il contient des [nodes](#node) et, pour le front, des [plugins](#plugin) et des [composants de toolbar](#composant-de-toolbar). |
| 25 | +La définition d'un bundle permet de configurer plusieurs RTE ou Renderers de manière identique. |
| 26 | + |
| 27 | +Détaillons maintenant les différents éléments contenu dans un bundle : |
| 28 | + |
| 29 | +### Node |
| 30 | + |
| 31 | +Une node est une partie du texte ou un élément visuel que l'utilisateur peut ajouter à son texte. Il peut s'agir par exemple d'images, d'émojis customs, ou de texte avec un fond coloré. |
| 32 | +Pour créer de nouvelles capacités/de nouveaux éléments dans le texte formatté, la première étape est de créer une `class` qui hérite de `ElementNode`, `TextNode` ou `DecoratorNode`. Pour voir les méthodes à implémenter, regardez [la doc de lexical](https://lexical.dev/docs/concepts/nodes#creating-custom-nodes). Comme indiqué plus bas dans la doc, on peut utiliser [`$config` et ne pas implémenter les 3 fonctions statiques](https://lexical.dev/docs/concepts/nodes#extending-elementnode-with-config). |
| 33 | + |
| 34 | +```{tip} |
| 35 | +Seule les `DecoratorNode` pourront être rendues avec une ReactNode côté front (cf. `DecoratorNode#decorate`). Si tu n'as pas envie d'écrire des opérations DOM, cela peut être une bonne solution 😉 |
| 36 | +``` |
| 37 | + |
| 38 | +Lorsqu'on applique des classes à des éléments, il faut faire bien attention à prendre celles du thème de l'éditeur, `editor.theme[className]`. Sinon, on pourrait oublier de les implémenter de l'autre côté (serveur/client) et le rendu serait alors différent ! |
| 39 | + |
| 40 | +Si on souhaite remplacer une node déjà définie, on peut enregistrer des [remplacements](https://lexical.dev/docs/concepts/node-replacement). Cela nous évite de devoir copier-coller tout notre code, et à chaque fois qu'une node remplacée sera créée, elle sera transformée en notre nouvelle node à l'aide de la fonction qu'on aura définie ! |
| 41 | + |
| 42 | +### Plugin |
| 43 | + |
| 44 | +Les plugins n'existent que côté front-end. Ce sont eux qui vont ajouter de la logique, on va pouvoir: |
| 45 | + |
| 46 | +- écouter des [évènements](https://lexical.dev/docs/concepts/commands), à l'aide de `editor.registerCommand()` |
| 47 | +- enregistrer des [transformers](https://lexical.dev/docs/concepts/transforms) avec `editor.registerNodeTransform()` |
| 48 | +- en react, utiliser `useEffect` |
| 49 | +- rendre un élément supplémentaire, un overlay par exemple |
| 50 | + |
| 51 | +```{admonition} TLDR |
| 52 | +:class: tip |
| 53 | +Un transformer, c'est du code qui va te permettre de transformer du contenu dans le RTE au fur et à mesure qu'il est ajouté. Par exemple, tu peux transformer automatiquement `:joy:` en l'émoji correspondant, 😂. |
| 54 | +``` |
| 55 | + |
| 56 | +### Composant de toolbar |
| 57 | + |
| 58 | +Ce qui permettra à l'utilisateur d'intéragir avec nos nodes depuis une interface. |
| 59 | + |
| 60 | +A l'heure actuelle, ces composants n'existent pas encore en tant que tel et font partie du composant `ToolbarPlugin`. Leur future séparation permettra d'ajouter facilement des composants (boutons, etc) custom dans cette toolbar. |
| 61 | + |
| 62 | +## Côté serveur |
| 63 | + |
| 64 | +Bien que le serveur n'ait pas à gérer l'édition en temps réel, il doit pouvoir effectuer quelques opérations sur le contenu généré par l'utilisateur. Cela inclut la validation du contenu lexical et l'export en HTML (pour pouvoir l'utiliser dans des emails par exemple). |
| 65 | + |
| 66 | +```{admonition} Structure Lexical |
| 67 | +La structure envoyée entre l'API et le client est un JSON (créé avec `LexicalNode#exportJSON`). Il contient les nodes imbriquées les unes dans les autres. |
| 68 | +``` |
| 69 | + |
| 70 | +### La validation |
| 71 | + |
| 72 | +La validation vérifie que le contenu fourni par l'utilisateur a bien une structure comprise par le serveur. Cela vérifie : |
| 73 | + |
| 74 | +- que c'est bien du JSON |
| 75 | +- que l'éditeur lexical le comprend |
| 76 | +- qu'il n'y a pas de node absente du bundle |
| 77 | +- qu'il n'y a pas de propriétés inconnues sur les nodes |
| 78 | + |
| 79 | +```{attention} |
| 80 | +Les propriétés des nodes doivent apparaitre dans le même sens lors de l'exportJSON côté front et côté serveur. |
| 81 | +``` |
| 82 | + |
| 83 | +### Le rendu |
| 84 | + |
| 85 | +Le rendu permet au serveur de transformer du contenu lexical en html. Il faut faire attention à deux points ici : |
| 86 | + |
| 87 | +- les méthodes `DecoratorNode#decorate` doivent être enlevées et le contenu de la node doit être traduit en instructions DOM dans `DecoratorNode#createDOM` |
| 88 | +- les styles appliqués sur le front doivent être réappliqués sur le DOM produit sur l'API. Cela peut nécessiter des modifications structurelles dans l'HTML généré. En cas de besoin, il est possible d'ajouter des conditions spécifiques dans `NodeStyleInjector.ts` |
0 commit comments