Modèle PHP

Rnode, Rblock, Mark_op, Rdoc — les classes du VDM

Rnode — fragment de texte

L'unité atomique du modèle. Un Rnode représente un fragment de texte avec ses marks actifs et ses données de couleur.

new Rnode('Hello ')                                              // texte brut
new Rnode('world',   ['bold'])                                   // gras
new Rnode('cliquer', ['link'], 'https://example.com', '_blank')  // lien
new Rnode('ici',     ['marker'], '', '', '#fef08a')              // surlignement
new Rnode('rouge',   ['color'],  '', '', '', '#dc2626')          // couleur texte

href/target ne sont sérialisés que si href !== ''. marker_color/text_color idem si non vides. Deux Rnodes adjacents avec les mêmes marks (et mêmes couleurs) fusionnent automatiquement après chaque opération.

Mark_op — les transformations

Toutes les transformations de marks passent par Mark_op (méthodes statiques). Le paramètre $from/$to est un offset en caractères dans la concaténation de tous les textes du bloc.

// "Hello world" → bold sur "world" (positions 6–11)
Mark_op::toggle($nodes, 'bold', 6, 11)   // toggle : retire si déjà present, sinon applique
Mark_op::apply($nodes,  'bold', 6, 11)   // force apply
Mark_op::remove($nodes, 'bold', 6, 11)   // force remove
Mark_op::reset_marks($nodes, 0, 11)      // efface tout (marks + href + couleurs)
Algorithme split_and_map
Avant  : [{ text: "Hello world", marks: [] }]

1. Split aux frontières [6, 11] :
   [{ "Hello ", [] }, { "world", [] }, { " today", [] }]

2. Applique fn() sur la portion chevauchante :
   [{ "Hello ", [] }, { "world", ["bold"] }, { " today", [] }]

3. Merge les nodes adjacents avec les mêmes marks :
   (si le texte d'après avait aussi bold, les deux fusionneraient)

Rblock — le bloc

Un Rblock porte le type, le contenu (Rnode[] pour les blocs texte, Rnode[][] pour les listes), et des données libres (data) pour les types non-texte (séparateur, image).

MéthodeDescription
inner_html()Rendu inline du contenu (paragraph/heading) — utilisé dans la vue éditeur
item_html(array $nodes)Rendu inline d'un item de liste
to_html()Rendu HTML complet du bloc pour l'export public
parse_inline_html(string $html)Parse le innerHTML d'un contenteditable → Rnode[]
parse_list_html(string $html)Parse les <li> d'une liste → Rnode[][]
is_list()Vrai si list_ul ou list_ol
editor_tag()Tag HTML à utiliser dans l'éditeur (p, h2, ul…)
Ordre des marks dans le rendu : Rblock applique les marks dans un ordre canonique (color → marker → bold → italic → underline → link) pour garantir un HTML cohérent quel que soit l'ordre dans lequel ils ont été appliqués.

Rdoc — le document

MéthodeDescription
Rdoc::make_default()Crée un document avec un paragraphe vide
Rdoc::from_json(string $json)Désérialise depuis JSON (stockage DB)
to_html()HTML de tous les blocs concaténés
to_array()Array PHP (pour json_encode)
find_block(string $id)Cherche un bloc par id, retourne null si absent
// Lire depuis DB et rendre
$doc  = Rdoc::from_json($article->content);
$html = $doc->to_html();

// Conversion liste → paragraph : conjonction configurable
Rdoc::$list_conjunction = 'and';  // défaut : 'et'