# Architecture

Pena (`Pena-tauri`) est une application [Tauri 2](https://tauri.app/) : un **backend Rust**
expose des commandes à un **frontend web** (HTML/CSS/JS vanilla, sans bundler). Le frontend
est servi en fichiers statiques depuis `src/`, le backend est compilé dans `src-tauri/`.

L'ensemble suit une **Clean Architecture** stricte, côté Rust comme côté JS.

## Vue d'ensemble

```
┌──────────────────────────── Frontend (src/, JS vanilla) ────────────────────────────┐
│  ui/        — composants d'affichage (home, sidebar, reader, css-modal)              │
│  state/     — état global minimal (app-state)                                        │
│  services/  — appels Tauri via invoke (markdown, files, watcher, themes)             │
│  router.js  — navigation entre vues (accueil / lecteur)                              │
└──────────────────────────────────────┬───────────────────────────────────────────────┘
                                        │  window.__TAURI__.core.invoke(...)
                                        │  window.__TAURI__.event.listen(...)
┌──────────────────────────────────────┴──── Backend (src-tauri/src/, Rust) ───────────┐
│  commands/        — points d'entrée #[tauri::command] (render, watch, theme)         │
│  application/     — services métier (render_service, file_service, theme_service)    │
│  infrastructure/  — implémentations concrètes (comrak, notify, fs, thèmes statiques) │
│  domain/          — entités et traits purs (MarkdownRenderer, ThemeRepository…)      │
│  lib.rs           — point d'assemblage (wiring + enregistrement des commandes)       │
└───────────────────────────────────────────────────────────────────────────────────────┘
```

## Backend Rust — couches

Le code Rust (`src-tauri/src/`) est découpé en quatre couches, avec des règles de dépendance
strictes.

| Couche | Rôle | Peut dépendre de | Ne doit PAS dépendre de |
|---|---|---|---|
| `domain/` | Entités et traits purs, zéro dépendance externe | rien | `application`, `infrastructure`, `commands` |
| `application/` | Services métier (orchestration des cas d'usage) | `domain` | `infrastructure`, `commands` |
| `infrastructure/` | Implémentations concrètes des traits du domaine | `domain` | `application`, `commands` |
| `commands/` | Commandes exposées à Tauri | `application`, `domain` | `infrastructure` (directement) |

### `domain/`
Définit les contrats, sans aucune dépendance technique :
- `markdown.rs` — trait `MarkdownRenderer { fn render(&self, content: &str) -> String }`
  et struct `RenderOptions` (tables, strikethrough, autolink, tasklist).
- `theme.rs` — struct `Theme { id, label }` et trait
  `ThemeRepository { fn list() -> Vec<Theme>; fn get_css(id) -> Option<String> }`.

### `application/`
Orchestration métier, dépend uniquement du domaine :
- `render_service.rs` — `render_string()` (rendu d'une chaîne) et `render_file()`
  (lecture du fichier puis rendu).
- `file_service.rs` — `list_markdown_files()` : valide le répertoire, collecte les `.md`,
  trie alphabétiquement.
- `theme_service.rs` — `list_themes()` et `get_theme_css()`, délégués au repository.

### `infrastructure/`
Implémentations concrètes des traits du domaine :
- `comrak_renderer.rs` — `ComrakRenderer` (toutes les extensions activées, pour les
  fichiers) et `ComrakPreviewRenderer` (sans extensions, pour les aperçus rapides). Fournit
  aussi `syntax_css_for_theme()` pour générer le CSS de coloration `syntect`. La syntaxe
  TypeScript est chargée depuis `resources/syntaxes/TypeScript.sublime-syntax`.
- `file_repository.rs` — `collect_md_files()` (parcours récursif, ignore les fichiers
  cachés, ne retient que les `.md`) et `read_file()`.
- `notify_watcher.rs` — boucle de débounce (80 ms) qui filtre les événements de la crate
  `notify` et émet l'événement Tauri `file-changed`.
- `theme_repository.rs` — `StaticThemeRepository` : les 6 thèmes et leur CSS sont intégrés
  au binaire via `include_str!()` (fichiers `resources/themes/*.css`).

### `commands/`
Points d'entrée Tauri qui instancient les implémentations concrètes et appellent les
services. Voir la référence complète : [Commandes Tauri](2.2-Commandes-Tauri.md).

### `lib.rs` — point d'assemblage
Seul endroit où les implémentations concrètes sont câblées. Il :
- enregistre les plugins `tauri-plugin-fs` et `tauri-plugin-dialog` ;
- gère l'état global `WatcherState` (un seul watcher actif à la fois) ;
- enregistre les 8 commandes via `generate_handler![]`.

## Frontend JS — couches

Le code JS (`src/`) suit le même esprit de séparation :

| Dossier | Rôle | Peut dépendre de |
|---|---|---|
| `ui/` | Composants d'affichage, sans logique métier ni appel Tauri direct | `services/`, `state/` |
| `state/` | État global de l'application (`app-state.js`) | — |
| `services/` | Appels Tauri (`invoke`) et logique de données | API Tauri |
| `router.js` | Navigation entre les vues (accueil / lecteur), orchestrateur | `services/`, `ui/`, `state/` |

**Règle importante** : les composants `ui/` ne font **jamais** d'appel Tauri directement ;
ils passent toujours par un service de `services/`.

### Services frontend
- `services/markdown.js` — `render_markdown`, `convert_file`
- `services/files.js` — `list_md_files`
- `services/watcher.js` — `start_watch`, `stop_watch`, écoute de `file-changed`
  (présent mais non utilisé par l'UI)
- `services/themes.js` — `list_themes`, `get_theme_css`

## Dépendances Rust principales

| Crate | Rôle |
|---|---|
| `tauri` (+ `tauri-plugin-fs`, `tauri-plugin-dialog`) | Framework applicatif, IPC, événements, dialogues |
| `comrak` | Rendu CommonMark + extensions |
| `syntect` | Coloration syntaxique des blocs de code |
| `notify` | Surveillance du système de fichiers |
| `serde` / `serde_json` | Sérialisation des DTO et payloads |

## Ressources intégrées au binaire

| Ressource | Emplacement | Usage |
|---|---|---|
| Thèmes rapides | `src-tauri/resources/themes/*.css` | Servis par `get_theme_css` |
| Syntaxe TypeScript | `src-tauri/resources/syntaxes/TypeScript.sublime-syntax` | Coloration des blocs TS |

Elles sont incluses à la compilation (`include_str!`), donc l'application n'a pas besoin de
fichiers externes pour fonctionner.

## Voir aussi

- [Commandes Tauri](2.2-Commandes-Tauri.md)
- [Build et compilation](../3-installation/3.3-Build.md)
- [Vue d'ensemble fonctionnelle](../1-fonctionnel/1.1-Vue-d-ensemble.md)
