Files
Pena/docs/2-technique/2.1-Architecture.md
T

7.0 KiB

Architecture

Pena (Pena-tauri) est une application Tauri 2 : 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.rsrender_string() (rendu d'une chaîne) et render_file() (lecture du fichier puis rendu).
  • file_service.rslist_markdown_files() : valide le répertoire, collecte les .md, trie alphabétiquement.
  • theme_service.rslist_themes() et get_theme_css(), délégués au repository.

infrastructure/

Implémentations concrètes des traits du domaine :

  • comrak_renderer.rsComrakRenderer (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.rscollect_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.rsStaticThemeRepository : 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.

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.jsrender_markdown, convert_file
  • services/files.jslist_md_files
  • services/watcher.jsstart_watch, stop_watch, écoute de file-changed (présent mais non utilisé par l'UI)
  • services/themes.jslist_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