# 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; fn get_css(id) -> Option }`. ### `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)