Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions efx/docs/fr/guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
## Guide de syntaxe

### Structure

* Éléments : `<Name ...>enfants</Name>` et auto-fermants `<Name .../>`.
* Les nœuds de texte et les interpolations `{expr}` sont autorisés à l’intérieur de `Label`/`Button`.
* Plusieurs éléments sont autorisés à la racine — un bloc avec une liste d’expressions sera généré.

### Interpolations

Vous pouvez insérer des expressions Rust arbitraires dans le texte :

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r#"<Label>Bonjour {1 + 1}</Label>"#);
```

---

### Sécurité des interpolations `{expr}`

Certains développeurs, habitués aux moteurs de templates PHP ou JavaScript, peuvent craindre que les expressions dans les templates soient dangereuses ou mélangent logique et balisage.

EFx fonctionne différemment :

* **Uniquement à la compilation** : `{expr}` est développé par le compilateur Rust. Il n’y a pas de `eval`, pas d’exécution de chaîne dynamique au runtime.
* **Typé et sûr** : le code inséré est du Rust normal, entièrement vérifié par le compilateur.
Si l’expression ne compile pas, le template échoue à la compilation.
* **Portée limitée** : les interpolations ne sont autorisées que dans des tags textuels comme `<Label>` ou `<Button>`, où elles sont développées en appels comme :

```rust
use efx_core::doc_prelude::*;
use efx::efx;

let user_name = "Max";

efx!(Ui::default(), "<Label>Bonjour {user_name}</Label>");
// s’étend en :
Ui::default().label(format!("Bonjour {}", user_name));
```
* **Aucun risque d’injection** : contrairement aux templates PHP, il est impossible pour des données non fiables d’introduire du nouveau code. Toutes les valeurs passent par `format!` / `Display`.

En résumé, EFx garde un style déclaratif tout en préservant les garanties de compilation de Rust.
Cela rend l’interpolation sûre et prévisible, loin des pratiques dynamiques et risquées des templates PHP classiques.

### Écrire directement du code UI en Rust n’est-il pas déjà sûr ?

Oui — écrire du Rust natif avec `egui` est déjà mémoire-sûr.
EFx n’ajoute pas de sécurité supplémentaire ici. Son but est différent :

* **Réduire le boilerplate** : au lieu de closures imbriquées, vous pouvez exprimer des layouts en balisage XML compact.
* **Préserver les garanties Rust** : les interpolations `{expr}` sont du Rust, vérifiées par le compilateur.
* **Rester compatible** : EFx se compile en appels `ui.*` normaux, vous pouvez mélanger librement snippets EFx et code `egui` écrit à la main.

En bref : Rust vous donne la sûreté mémoire. EFx vous donne *l’ergonomie développeur* par-dessus, sans sacrifier la sécurité ni le contrôle.

#### Échapper les accolades

Le texte `{` et `}` s’obtient via `{{` et `}}` respectivement.

### Attributs de tag (depuis 0.4)

Ils s’écrivent comme en XML : `name="value"`.
Pour l’instant, les attributs sont **analysés** et disponibles dans l’AST,
mais le renderer **ne les utilise pas** — l’API de traitement sera ajoutée dans de futures versions.

```xml
<Label color="green" size="lg">Salut</Label>
```

### Erreurs de compilation

* Tag inconnu → `compile_error!`.
* Violation des restrictions d’un tag (ex. enfants de `<Separator/>`) → `compile_error!`.
* Fragment invalide dans une interpolation `{ … }` → `compile_error!` avec extrait de code source.

### Débogage

Si vous voulez voir ce que génère `efx!`, compilez avec :

```bash
RUSTFLAGS="--emit=mir,llvm-ir"
```
290 changes: 290 additions & 0 deletions efx/docs/fr/tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
## Tags supportés (v0.4+)

> À partir de la version 0.5 certains tags supportent des attributs.
> Les attributs inconnus produisent un `compile_error!`.

### `Column`

Conteneur vertical. Génère `ui.vertical(|ui| { ... })`.

**Attributs**

* `align="left|center|right"` — alignement horizontal des enfants.
* `gap="N"` — espacement vertical entre enfants (f32).
* `padding="N"` — marge supplémentaire haut/bas (f32).

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r#"<Column gap="10" padding="6" align="center">
<Label>Titre</Label>
<Label size="12">Sous-titre</Label>
</Column>"#);
```

### `Row`

Conteneur horizontal. Génère `ui.horizontal(|ui| { ... })`.

**Attributs**

* `align="top|center|bottom"` — alignement vertical des enfants.
* `gap="N"` — espacement horizontal entre enfants (f32).
* `wrap="true|false"` — retour automatique à la ligne si dépassement.
* `padding="N"` — marge supplémentaire gauche/droite (f32).

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r#"<Row gap="8" padding="4" align="center"><Label>A</Label><Label>B</Label></Row>"#);

efx!(Ui::default(), r#"<Row wrap="true"><Label>Item1</Label><Label>Item2</Label><Label>Item3</Label></Row>"#);
```

### `Label`

Widget texte. Seuls du texte et des interpolations (`{expr}`) sont autorisés comme enfants.

**Attributs**

* `color="name|#RRGGBB[AA]"` — couleur du texte.
* `size="N"` — taille de police (f32).
* `bold="true|false"`.
* `italic="true|false"`.
* `underline="true|false"`.
* `strike="true|false"`.
* `monospace="true|false"`.
* `wrap="true|false"` — activer le retour à la ligne.

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r##"<Label color="#66CCFF" size="16" bold="true">Bonjour utilisateur</Label>"##);
```

### `Separator`

Séparateur auto-fermable. Aucun enfant autorisé (sinon `compile_error!`).

**Attributs**

* `space="N"` — espacement uniforme avant et après (f32).
* `space_before="N"` — espacement au-dessus.
* `space_after="N"` — espacement en dessous.

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r#"<Separator space="12"/>"#);
efx!(Ui::default(), r#"<Separator space_before="8" space_after="4"/>"#);
```

```rust,compile_fail
use efx_core::doc_prelude::*;
use efx::*;

/// compile_fail
efx!(Ui::default(), "<Separator>enfant</Separator>");
```

### `Button`

Bouton — c’est le seul tag qui retourne une valeur de type `Resp` à la racine d’une expression.

**Attributs**

* `fill="color"` — couleur de fond.
* `rounding="N"` — rayon d’arrondi (f32).
* `min_width="N", min_height="N"` — taille minimale.
* `frame="true|false"` — dessiner fond/bordure.
* `enabled="true|false"` — activer/désactiver le bouton.
* `tooltip="text"` — info-bulle au survol.

```rust
use efx_core::doc_prelude::*;
use efx::*;

let resp: Resp = efx!(Ui::default(), r#"<Button rounding="8" enabled="false" tooltip="Bientôt">Exécuter</Button>"#);
assert!(!resp.clicked());
```

### `Hyperlink`

Lien cliquable. Génère `ui.hyperlink(url)` ou `ui.hyperlink_to(label, url)`.

**Attributs**

* `url="..."` — adresse de destination (obligatoire).
* `open_external="true|false"` — ouvrir dans le navigateur système (par défaut true).
* `color="name|#RRGGBB[AA]"` — couleur du texte du lien.
* `underline="true|false"` — souligner le texte du lien (par défaut true).
* `tooltip="text"` — info-bulle au survol.

Utilisation multiplateforme :

* **Web :** rendu comme un lien `<a>` standard.
* **Desktop (eframe, bevy\_egui) :** ouvre le navigateur système via `ui.hyperlink(...)`.
* **Overlays jeu/outils :** pratique pour relier docs, dépôts, aide.
* **Apps hors-ligne :** avec schémas d’URL personnalisés (ex. `help://topic`).

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r##"
<Column>
<Hyperlink url="https://efxui.com" color="#66CCFF" tooltip="Site du projet"/>
<Hyperlink url="help://about" open_external="false">À propos</Hyperlink>
</Column>
"##);
```

### `TextField`

Champ de saisie (une ou plusieurs lignes). Génère `egui::TextEdit` et l’insère via `ui.add(...)`. Doit être auto-fermable (pas d’enfants).

**Attributs**

* `value="<expr>"` — **obligatoire**. Expression Rust de type `String`, ex. `state.name`. Le générateur prend automatiquement `&mut (<expr>)`.
* `hint="text"` — texte indicatif affiché quand vide.
* `password="true|false"` — masquer les caractères (uniquement en mode ligne simple).
* `width="N"` — largeur souhaitée (f32).
* `multiline="true|false"` — éditeur multi-lignes (`TextEdit::multiline`).

```rust
use efx_core::doc_prelude::*;
use efx::*;

#[derive(Default)]
struct State { name: String }

let mut state = State::default();

// Ligne simple avec placeholder et largeur
efx!(Ui::default(), r#"<TextField value="state.name" hint="Votre nom" width="220"/>"#);

// Champ mot de passe
efx!(Ui::default(), r#"<TextField value="state.name" password="true"/>"#);

// Éditeur multi-lignes
efx!(Ui::default(), r#"<TextField value="state.name" multiline="true" width="320"/>"#);
```

### `CentralPanel`

Zone principale remplissant tout l’espace disponible. Enveloppe ses enfants dans `egui::CentralPanel` et applique éventuellement un `Frame`.

**Attributs**

* `frame="true|false"` — utiliser un frame par défaut (`true`, par défaut) ou aucun (`false`).
* `fill="name|#RRGGBB[AA]"` — couleur de fond.
* `stroke-width="N"` — épaisseur du trait (f32).
* `stroke-color="name|#RRGGBB[AA]"` — couleur du trait.
* `padding="N"` — marge intérieure (f32).
* `padding-left|padding-right|padding-top|padding-bottom="N"`.
* `margin="N"` — marge extérieure (f32).
* `margin-left|margin-right|margin-top|margin-bottom="N"`.

```rust,no_run
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r##"
<CentralPanel fill="#101014" padding="12" stroke-width="1" stroke-color="#222638">
<Column gap="8">
<Label size="18" bold="true">Tableau de bord</Label>
<Separator space="6"/>
<Row gap="12">
<Label>Bienvenue !</Label>
<Hyperlink url="https://efxui.com">Docs</Hyperlink>
</Row>
</Column>
</CentralPanel>
"##);
```

### `ScrollArea`

Conteneur défilant basé sur `egui::ScrollArea`. Enveloppe ses enfants et fournit un défilement vertical/horizontal/les deux.

**Attributs**

* `axis="vertical|horizontal|both"` — axe de défilement (par défaut: vertical).
* `always-show="true|false"` — toujours afficher la barre de défilement.
* `max-height="N"` — hauteur maximale (f32).
* `max-width="N"` — largeur maximale (f32).
* `id="text"` — identifiant pour persister l’état.
* `bottom="true|false"` — rester collé en bas (logs/chats).
* `right="true|false"` — rester collé à droite.

```rust,ignore
use efx_core::doc_prelude::*;
use efx::*;

// Panneau log vertical collé en bas
efx!(Ui::default(), r#"
<ScrollArea axis="vertical" max_height="200" always_show="true" id="log-pane" stick_to_bottom="true">
<Column gap="6">
<Label bold="true">Log :</Label>
<Label>Ligne 1</Label>
<Label>Ligne 2</Label>
<Label>Ligne 3</Label>
</Column>
</ScrollArea>
"#);

// Scroll horizontal
efx!(Ui::default(), r#"
<ScrollArea axis="horizontal" max_width="320" always_show="true">
<Row gap="12">
<Label>Item 1</Label>
<Label>Item 2</Label>
<Label>Item 3</Label>
<Label>Item 4</Label>
</Row>
</ScrollArea>
"#);

// Les deux directions (ex. grosse grille)
efx!(Ui::default(), r#"
<ScrollArea axis="both" max_width="400" max_height="220">
<Column gap="8">
<Row gap="8"><Label>A1</Label><Label>A2</Label><Label>A3</Label><Label>A4</Label></Row>
<Row gap="8"><Label>B1</Label><Label>B2</Label><Label>B3</Label><Label>B4</Label></Row>
<Row gap="8"><Label>C1</Label><Label>C2</Label><Label>C3</Label><Label>C4</Label></Row>
<Row gap="8"><Label>D1</Label><Label>D2</Label><Label>D3</Label><Label>D4</Label></Row>
</Column>
</ScrollArea>
"#);
```

### `Heading`

Titre de section. Génère `ui.heading(text)` avec des styles optionnels.

**Attributs**

* `level="1..6"` — niveau de titre (entier).
*Défaut :* `1`. Correspond aux styles prédéfinis d’`egui`.
* `size="N"` — taille de police personnalisée (f32).
* `color="name|#RRGGBB[AA]"` — couleur du texte.
* `tooltip="text"` — info-bulle au survol.

```rust
use efx_core::doc_prelude::*;
use efx::*;

efx!(Ui::default(), r##"
<Column gap="8">
<Heading level="1">Titre principal</Heading>
<Heading level="2" color="#66CCFF">Section</Heading>
<Heading level="3" size="14" tooltip="Sous-titre">Note</Heading>
</Column>
"##);
```

L’attribut `level` contrôle le style de base (h1–h6), tandis que `size` et `color` permettent d’affiner l’apparence.