Rédac
Éditeur WYSIWYG par blocs — état server-side (PHP VDM)
http://alluvia.local/demo/redac
Philosophie — pourquoi PHP comme VDM ?
Un éditeur WYSIWYG classique maintient l'état dans le DOM : le HTML du contenteditable
est le document. C'est simple à démarrer, mais les transformations (mettre en gras, convertir
un titre en paragraphe) passent par document.execCommand() ou des manipulations DOM
directes — fragiles, dépendantes du navigateur, et qui produisent souvent du HTML "sale".
Rédac choisit une autre approche : l'état du document vit côté PHP, dans un modèle de données explicite. Le navigateur reste simple — il capte les frappes (contenteditable) et envoie des opérations à PHP via HTMX. PHP applique la transformation, régénère le HTML propre, et le renvoie.
contenteditable, sans round-trip.
Rapide, natif. Le texte est synchronisé avec PHP sur le blur du bloc.
Rnode[]), régénère le HTML du bloc, HTMX swaps. Toujours propre, toujours cohérent.
Architecture globale
Rédac a deux parties qui communiquent via HTMX :
PHP — src/Redac/
├── Redac.php ← service objet injectable dans tout contrôleur
├── Rnode.php ← fragment de texte + marks (bold, link, marker…)
├── Rblock.php ← bloc typé (paragraph, h2, list_ul, separator, image…)
├── Rdoc.php ← document = liste ordonnée de Rblocks
└── Mark_op.php ← opérations sur les marks (toggle, apply, split_and_map)
JS — vitejs/src/redac/
├── main.js ← bundle Vite standalone (Bootstrap + htmx inclus)
└── js/ ← 13 modules ES (inline_menu, tune, slash, panels…)
Ce que voit l'utilisateur
Bouton +
Apparaît au survol de chaque bloc. Ouvre un block picker pour choisir
le type du nouveau bloc à insérer.
Bouton ⋮ (Tune)
Ouvre le menu contextuel du bloc : déplacer, supprimer, définir id/classes CSS,
et les options propres au type (couleur séparateur, URL image…).
Menu inline
Sélectionner du texte → barre flottante : gras, italic, souligné, lien, surlignement, couleur texte, reset, source HTML.Slash picker (/)
Taper / dans un bloc vide ouvre un picker filtrable pour convertir
le bloc en n'importe quel type (paragraph, h1–h6, liste, séparateur, image).