@synapxlab/wysiwyg

Éditeur WYSIWYG · Pagebuilder TypeScript — zéro dépendance runtime.
Dessin vectoriel natif, grille multi-colonnes, Mermaid, KaTeX, inspecteur CSS. Drop-in dans n'importe quel projet.

  • Zéro dépendance runtime (pas de React, Vue, jQuery)
  • Éditeur vectoriel natif intégré — dessin, texte, rotation, propriétés
  • Pagebuilder — grille flexbox, blocs structurés, mise en page multi-colonnes
  • Mermaid, KaTeX, Excalidraw opt-in — zéro impact bundle
  • ESM + CJS — fonctionne dans tous les frameworks
TypeScript Pagebuilder ESM CJS MIT
editor.ts
import { WysiwygEditor } from '@synapxlab/wysiwyg'; import '@synapxlab/wysiwyg/style.css'; const editor = new WysiwygEditor(); document.getElementById('app') .appendChild(editor.el); // Lire / écrire editor.getValue(); // → string HTML editor.setValue('<p>Hello</p>');

Démo interactive

✓ Copié !
Chargez un template ci-dessous pour explorer les fonctionnalités

21 templates à charger dans l'éditeur

📝

Article de blog

Titre, intro, liste à puces, blockquote et section code. Structure éditoriale classique.

Simple Headings Blockquote
📧

Newsletter mensuelle

Header coloré, mise en page 2 colonnes (contenu + sidebar chiffres), bouton CTA.

Simple Colonnes CTA
🔀

Pipeline CI/CD

Flowchart LR complet : lint → tests → build → Docker → staging → approval → prod.

Mermaid Flowchart Tableau
🔑

Flux Auth OAuth2

Diagramme de séquence : Frontend → API Gateway → Auth Service → Redis Cache.

Mermaid Sequence
📅

Planning Gantt Q2

Roadmap 4 sprints avec tâches done/active/à venir et milestone de release.

Mermaid Gantt Blockquote
💳

Grille Pricing

3 colonnes flexbox (Starter / Pro / Enterprise) avec tarifs, features et CTA différenciés.

Grille 3 col CTA
📊

Rapport Dashboard

KPIs en 4 colonnes, pie chart sources de trafic, tableau top pages avec métriques.

Mermaid Pie Colonnes Tableau
📖

Documentation API

Référence technique avec blocs code, tableau de props, notes blockquote et exemples.

Code blocks Tableau Blockquote
🛒

Workflow commande

State diagram du cycle de vie e-commerce : panier → paiement → expédition → retour.

Mermaid State Règles métier
🗄️

Schéma BDD SaaS

Diagramme ER multi-tenant : Organization → Workspace → Project + Users + AuditLog.

Mermaid ER Architecture
🍽️

Menu gastronomique

Carte élégante avec photos Unsplash, entrées / plats / desserts, mise en page colonnes.

Colonnes Images Restaurant
🥖

Bistrot parisien

Carte brasserie avec formule du jour, tableau de prix, galerie desserts et photos.

Tableau Images Restaurant

Physique — Équations fondamentales

E=mc², équation de Schrödinger, équations de Maxwell. Formules en mode bloc et inline.

KaTeX Sciences

Mathématiques — Analyse

Série de Taylor, intégrale de Gauss, formule d'Euler. Mix bloc / inline dans le texte.

KaTeX Maths
μ

Statistiques & Machine Learning

Distribution normale, régression linéaire, gradient descent — avec formules et explications.

KaTeX ML
✏️

Architecture microservices

Schéma d'architecture avec API Gateway, services, bases de données et queues de messages.

Excalidraw Architecture
🖼️

Wireframe landing page

Maquette basse fidélité avec header, hero, features, pricing et footer.

Excalidraw UI/UX
🧠

Mind map — Stratégie produit

Carte mentale avec branches : Vision, Roadmap, Personas, KPIs, Risques.

Excalidraw Produit
🔄

User flow — Onboarding

Parcours utilisateur de l'inscription à l'activation du compte, avec décisions et étapes.

Excalidraw UX
📋

Board Kanban Sprint

Tableau Kanban avec colonnes Todo / In Progress / Review / Done et cartes de tâches.

Excalidraw Agile
🍣

Sushi Bar japonais

Menu épuré dark-mode avec plateaux, ramen, photos de plats et section livraison.

Grille Images Restaurant
🧾

Flux facturation électronique

Cycle de vie complet d'une facture : création, validation, envoi, paiement, relance — diagramme Mermaid interactif.

Mermaid ERP Finance
📦

Processus commande B2B

Séquence complète Client → Commercial → ERP → Entrepôt → Logistique avec échanges de messages et validations.

Mermaid ERP Supply Chain
🚚

Pipeline livraison e-commerce

Flux de traitement d'une commande en ligne : panier, paiement, préparation, expédition, livraison, retour.

Mermaid E-commerce Logistique
🔬

Analyse de signal — Mix complet

Transformée de Fourier en KaTeX, pipeline FFT en Mermaid et signal sinusoïdal dessiné en SVG natif.

KaTeX Mermaid SVG Sciences

Carte de visite numérique

Profil dev avec 3 QR codes générés à la volée — site web, GitHub, npm. Éditable en un clic.

QR Code Carte de visite

Presets toolbar — reconfigurer l'éditeur à la volée

Chaque preset correspond à une configuration toolbar utilisée dans l'ERP Adliss.

🚀 Installation

npm install @synapxlab/wysiwyg
yarn add @synapxlab/wysiwyg

Modules optionnels :

# Diagrammes Mermaid
npm install mermaid

# Formules mathématiques KaTeX
npm install katex

# Dessins Excalidraw (nécessite React 18)
npm install @excalidraw/excalidraw react react-dom --legacy-peer-deps

Ou via CDN (ESM) :

<script type="module">
  import { WysiwygEditor } from 'https://cdn.jsdelivr.net/npm/@synapxlab/wysiwyg/dist/wysiwyg.es.js';
  import 'https://cdn.jsdelivr.net/npm/@synapxlab/wysiwyg/dist/style.css';
</script>

⚡ Démarrage rapide

import { WysiwygEditor } from '@synapxlab/wysiwyg';
import '@synapxlab/wysiwyg/style.css';

const editor = new WysiwygEditor({
  upload: async (file) => {
    const fd = new FormData();
    fd.append('file', file);
    return (await (await fetch('/upload', { method:'POST', body:fd })).json()).url;
  },
});
document.getElementById('app').appendChild(editor.el);

editor.setValue('<p>Bonjour <strong>monde</strong></p>');
editor.onChange = () => console.log(editor.getValue());
const { WysiwygEditor } = require('@synapxlab/wysiwyg');

const editor = new WysiwygEditor();
document.getElementById('app').appendChild(editor.el);

🔧 Options toolbar

Tous les groupes sont activés par défaut. Passez false pour désactiver.

new WysiwygEditor({
  toolbar: { mermaid: true, math: true, draw: true, excalidraw: true, twig: false }, // opt-in
  wordCount: true,
  upload: async (file: File) => 'https://…/url.jpg',
  mermaid: mermaidInstance,     // requis si toolbar.mermaid: true
  katex: katexInstance,         // requis si toolbar.math: true
  excalidraw: { Excalidraw, exportToSvg, React, ReactDOM }, // requis si toolbar.excalidraw: true
});
{
  source, formatHtml, history, fullscreen,
  lists, align, direction,
  link, image, table, grid,
  heading, font, textColor,
  blockquote, divider, specialChars,
  mermaid,    // opt-in — passer opts.mermaid aussi
  math,       // opt-in — passer opts.katex aussi
  draw,       // opt-in — éditeur vectoriel natif, zéro dépendance
  excalidraw, // opt-in — passer opts.excalidraw aussi
  twig,       // opt-in — 27 snippets Twig prêts
}

🎯 Intention de sortie (HTML / PDF)

L'option intent: 'html' | 'pdf' de WysiwygOptions indique à l'éditeur l'usage auquel le résultat de getValue() est destiné.

  • intent: 'pdf' optimise le HTML pour wkhtmltopdf, dompdf et mPDF : les tableaux utilisent des largeurs figées en centimètres avec table-layout:fixed, les conteneurs de défilement responsive sont retirés et la propriété CSS vertical-align est aussi écrite dans l'attribut HTML valign, pour les moteurs qui ignorent parfois ce style sur les cellules.
  • intent: 'html', valeur par défaut, enveloppe les tableaux à largeur fixe dans un conteneur à défilement horizontal pour préserver un affichage responsive dans le navigateur, puis nettoie les attributs parasites superflus.

Sécurité Twig : le code Twig présent dans le contenu — {% %} et {{ }} — n'est jamais transformé ni altéré par la normalisation, quelle que soit l'intention choisie.

editor.getRawValue() retourne le HTML brut, sans aucune normalisation d'intention. Utilisez-le pour sauvegarder une version source indépendante du rendu final.

Pour une normalisation manuelle hors de l'éditeur, le package exporte applyIntent(html, intent), normalizeForPdf(html), normalizeForHtml(html) et le type WysiwygIntent.

import {
  WysiwygEditor,
  applyIntent,
  normalizeForPdf,
  normalizeForHtml,
} from '@synapxlab/wysiwyg';
import type { WysiwygIntent } from '@synapxlab/wysiwyg';

const editor = new WysiwygEditor({ intent: 'pdf' });
const pdfHtml = editor.getValue();    // HTML normalisé pour le PDF
const sourceHtml = editor.getRawValue(); // HTML brut

const intent: WysiwygIntent = 'pdf';
const manualPdf = applyIntent(sourceHtml, intent);
const pdfOnly = normalizeForPdf(sourceHtml);
const htmlOnly = normalizeForHtml(sourceHtml);

🧰 Presets

WYSI_PRESETS est un dictionnaire de configurations de toolbar prêtes à l'emploi, conçues pour les cas d'usage courants :

  • product — fiches produit e-commerce, avec un formatage minimal : texte, gras, italique, liens et listes.
  • mini — éditeur ultra-léger pour les libellés et descriptions courtes.
  • small — usage rédactionnel courant, avec un bon compromis entre légèreté et fonctionnalités.
  • bill — facturation et sortie PDF, avec tableaux et mise en page figée.
  • pdf — documents PDF complets, notamment les contrats, devis et rapports, avec une toolbar riche orientée impression.
  • entity — templates Twig pour les entités métier d'un ERP ou CRM : variables, boucles et conditions.
  • full — toutes les fonctionnalités activées, sans restriction.

resolvePreset(nom, surcharges?) retourne un objet WysiwygOptions prêt à fournir au constructeur et fusionne le preset choisi avec les surcharges optionnelles. Pour une configuration très ciblée, toolbarOnly(...clés) construit un WysiwygToolbarConfig qui n'active que les groupes indiqués.

import {
  WysiwygEditor,
  WYSI_PRESETS,
  resolvePreset,
  toolbarOnly,
} from '@synapxlab/wysiwyg';

const editor = new WysiwygEditor(
  resolvePreset('pdf', { statusbarLabel: 'Devis' }),
);

const customToolbar = toolbarOnly('bold', 'italic', 'link');
console.log(WYSI_PRESETS.pdf, customToolbar);

📖 API publique

editor.getValue(): string       // HTML courant
editor.setValue(html: string)   // Injecter du contenu
editor.focus(): void            // Placer le curseur
editor.onChange?: () => void   // Appelé à chaque modif
editor.el: HTMLElement          // Élément racine à monter

Note : editor.el doit être monté dans le DOM avant d'appeler setValue().

Types TypeScript

import type { WysiwygOptions, WysiwygToolbarConfig } from '@synapxlab/wysiwyg';

🧩 Mermaid (opt-in)

Injectez votre propre instance Mermaid v10+. Zéro impact bundle si non utilisé.

import mermaid from 'mermaid';
mermaid.initialize({ startOnLoad: false });

new WysiwygEditor({ mermaid, toolbar: { mermaid: true } });
  • Flowchart, sequence, gantt, pie, stateDiagram, erDiagram
  • Cliquez un diagramme existant pour le ré-éditer
  • Erreurs affichées inline dans la modale
  • Blocs ```mermaid``` dans le source HTML strippés automatiquement

∑ KaTeX — Formules mathématiques (opt-in)

Injectez votre propre instance KaTeX. Zéro impact bundle si non utilisé. Chargez le CSS KaTeX séparément.

import katex from 'katex';
import 'katex/dist/katex.min.css';

new WysiwygEditor({ katex, toolbar: { math: true } });
  • Cliquez le bouton Σ → saisissez la formule LaTeX (ex. \frac{a}{b})
  • Mode bloc (centré, $$...$$) ou mode inline (dans le texte, $...$)
  • Les délimiteurs $$...$$ / $...$ sont retirés automatiquement
  • Cliquez une formule existante → rouvre la modale avec le code pré-rempli
  • Stocké sous <div|span class="be-math" data-math-code="...">

🖊️ Éditeur vectoriel natif (opt-in)

Dessinez et annotez directement dans le contenu. L'éditeur SVG est désormais un package autonome — installez-le séparément puis injectez-le comme dépendance.

Installation

npm install @synapxlab/draw

Intégration

import { WysiwygEditor } from '@synapxlab/wysiwyg';
import { DrawEditor } from '@synapxlab/draw';
import '@synapxlab/draw/style.css';

new WysiwygEditor({
  draw: DrawEditor,
  toolbar: { draw: true },
});
  • 7 outils — sélection, crayon, rectangle, ellipse, ligne, flèche, texte multiligne
  • Sélection → 8 poignées de redimensionnement + rotation libre
  • Support tactile — fonctionne sur tablette et mobile
  • Double-clic sur un texte → édition en place
  • Panneau propriétés : couleur, arrière-plan, style texte, transparence, z-order
  • Annuler Ctrl+Z, supprimer Suppr
  • Clic sur un dessin inséré → panneau style + bouton Modifier le dessin

Documentation complète @synapxlab/draw →

▣ QR Code (opt-in)

Insérez et modifiez des QR codes SVG directement dans le contenu — couleurs, taille, correction d'erreur. Basé sur @synapxlab/qrcode, zéro dépendance runtime.

Installation

npm install @synapxlab/qrcode

Intégration

import { WysiwygEditor } from '@synapxlab/wysiwyg';
import { QRCode } from '@synapxlab/qrcode';

new WysiwygEditor({
  qrcode: QRCode,
  toolbar: { qrcode: true },
});
  • Génération SVG inline — retaillable à l'infini, zéro canvas
  • Couleur des modules, couleur de fond, marge, niveau de correction L/M/Q/H
  • Clic sur un QR inséré → modale de modification (toutes les options)
  • Données stockées en data-qr-* — re-générables côté serveur

Documentation complète @synapxlab/qrcode →

🔊 Lecture audio

Le bouton de toolbar audio, actif par défaut, lit à voix haute la sélection courante ou, si aucun texte n'est sélectionné, l'ensemble du contenu de l'éditeur. Un second clic arrête immédiatement la lecture en cours.

Le bouton est automatiquement masqué lorsque l'API Web Speech Synthesis n'est pas disponible dans le navigateur : aucune configuration de compatibilité n'est nécessaire. L'option lang accepte un code de langue BCP 47, par exemple fr-FR ou en-US, afin de forcer la langue de synthèse.

La classe exportée SpeechReader peut aussi être utilisée indépendamment de l'éditeur. Elle expose speak(texte), stop(), toggle(texte), l'événement onStateChange et la méthode statique SpeechReader.isSupported().

import { WysiwygEditor, SpeechReader } from '@synapxlab/wysiwyg';

const editor = new WysiwygEditor({
  lang: 'fr-FR',
  toolbar: { audio: true },
});

if (SpeechReader.isSupported()) {
  const reader = new SpeechReader();
  reader.onStateChange = (isSpeaking) => console.log(isSpeaking);
  reader.speak('Bonjour depuis SynapxLab.');
  reader.toggle('Un second appel bascule entre lecture et arrêt.');
  reader.stop();
}

🌿 Twig snippets (opt-in)

Activez le panneau de snippets Twig pour insérer rapidement des variables, structures et filtres dans le contenu. Les snippets sont insérés en texte brut — traités nativement par votre moteur Twig côté serveur.

new WysiwygEditor({
  toolbar: { twig: true },
});
  • Cliquez le bouton { } → panneau latéral avec snippets groupés par catégorie
  • 6 catégories intégrées : Variable, Structure, Filtre, Client, Facture, Système
  • Coloration syntaxique Twig en mode source (variables {{ }} et blocs {% %})
  • Snippets personnalisés injectables via twigSnippets: [ { cat, label, code } ]

Variables & structures

Accès aux données du contexte, conditions et boucles :

{{ customer.company }}           {# Société #}
{{ invoice.date|date('d/m/Y') }} {# Date formatée #}
{{ invoice.total_ttc|number_format(2, ',', ' ') }} €

{% if invoice.status == 'PAID' %}
  Facture réglée ✓
{% else %}
  En attente de paiement
{% endif %}

{% for line in invoice.lines %}
  {{ line.label }} — {{ line.qty }} × {{ line.unit_price }} €
{% endfor %}

Filtres natifs Twig

{{ texte|upper }}                     {# MAJUSCULES #}
{{ texte|lower }}                     {# minuscules #}
{{ texte|nl2br }}                     {# Sauts de ligne → 
#} {{ variable|default('N/A') }} {# Valeur par défaut #} {{ tableau|length }} {# Nombre d'éléments #} {{ date|date('d/m/Y') }} {# Format date #} {{ nombre|number_format(2,',',' ') }} {# 1 234,56 #}

Filtres d'extension Twig personnalisés

Injectez vos propres filtres métier via twigSnippets — ils restent dans votre projet et ne sont pas embarqués dans le package :

{# Montant en lettres → "MILLE DEUX CENTS EUROS" #}
{{ invoice.total_ttc|asLetters }}

{# Date en lettres → "le 24 mars 2026" #}
{{ invoice.date|asLetters }}

{# Expressions de date dynamiques résolues à l'exécution #}
{{ "Rapport de {{mount/year}}"|dateExpression(invoice.date) }}
{# → "Rapport de Mars 2026" #}

{# Traduction de valeurs BDD (DRAFT, PAID, BANK_TRANSFER…) #}
{{ "Statut : {{status}}"|Expression('status', invoice.status) }}
{# → "Statut : Payé" #}

{# JSON sécurisé pour attributs HTML #}
{# Traduction i18n #} {{ __('invoice.title') }}

Injection de snippets personnalisés

Passez vos filtres métier via l'option twigSnippets — chaque entrée a une catégorie, un libellé et le code à insérer :

new WysiwygEditor({
  toolbar: { twig: true },
  twigSnippets: [
    { cat: 'Mon ERP', label: '|asLetters',     code: 'montant en lettres' },
    { cat: 'Mon ERP', label: '|dateExpression', code: 'expression de date' },
    { cat: 'Mon ERP', label: '|jsonAttr',       code: 'json pour attribut HTML' },
  ],
});

🎨 Thème CSS vars

Toutes les couleurs dans des variables CSS scopées à .be-wysiwyg.

.be-wysiwyg {
  --be-primary:    #4f46e5;
  --be-bg:         #f8f9fa;
  --be-surface:    #ffffff;
  --be-border:     #e5e7eb;
  --be-text:       #111827;
  --be-radius:     6px;
  --be-font:       system-ui, sans-serif;
  --be-font-mono:  'Courier New', monospace;
}
.be-wysiwyg {
  --be-primary:    #6366f1;
  --be-bg:         #0f172a;
  --be-surface:    #1e293b;
  --be-border:     #334155;
  --be-text:       #f1f5f9;
}

🔧 Boutons personnalisés

Injectez vos propres boutons en fin de toolbar via l'option customButtons. Chaque bouton reçoit le HTML courant de l'éditeur au clic — idéal pour sauvegarder, exporter, envoyer, etc.

La démo ci-dessus en contient un : le bouton (Télécharger le HTML) en fin de toolbar.

new WysiwygEditor({
  customButtons: [
    {
      icon: 'REC',           // texte court ou SVG string
      title: 'Enregistrer',
      onClick: (html, editor) => {
        fetch('/save', { method: 'POST', body: html });
      },
    },
    {
      icon: '<svg …/>',     // SVG inline
      title: 'Télécharger le HTML',
      onClick: (html) => {
        const blob = new Blob([html], { type: 'text/html' });
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = 'export.html';
        a.click();
      },
    },
  ],
});

Interface WysiwygCustomButton

PropriétéTypeDescription
iconstringSVG string ou texte court (max ~4 car.)
titlestringInfobulle (tooltip)
onClick(html, editor) => voidCallback — reçoit le HTML courant et l'instance éditeur
classNamestring?Classe CSS supplémentaire sur le bouton (optionnel)

🧩 Addons WordPress & PrestaShop

Un plugin WordPress et un module PrestaShop prêts à l'emploi sont disponibles dans le dossier addons/ du dépôt GitHub @synapxlab/wysiwyg. Ils permettent d'intégrer l'éditeur sans écrire de JavaScript.

La commande suivante génère les deux archives ZIP prêtes à installer :

npm run package:addons

Dans le HTML, ajoutez la classe synapxlab-wysiwyg à un <textarea>. L'addon le détecte automatiquement et instancie l'éditeur à sa place. Les attributs data-preset, data-intent, data-height et data-label règlent respectivement le preset, l'intention html ou pdf, la hauteur en pixels et le libellé de la barre de statut.

<textarea
  class="synapxlab-wysiwyg"
  data-preset="pdf"
  data-intent="pdf"
  data-height="520"
  data-label="Devis"
></textarea>

Site sans bundler : le bundle IIFE dist/wysiwyg.global.js expose directement l'éditeur sous window.SynapxWysiwyg après son chargement avec une simple balise <script>.

👁 Rendu final

Le bouton Afficher sous l'éditeur ouvre une modale qui affiche le HTML généré en rendu final, encapsulé dans un conteneur .wysiwyg_view.

Ce rendu correspond à un affichage dans une page HTML classique — identique à ce que produirait $twig->createTemplate($html) côté serveur.

  • ✅ Typographie complète : titres, paragraphes, listes, blockquote, code
  • ✅ Tableaux avec zebra-stripes
  • ✅ Diagrammes Mermaid (SVG inline)
  • ✅ Formules KaTeX (HTML déjà rendu + CSS chargé)
  • ✅ QR codes (SVG inline)
  • ✅ Dessins vectoriels (SVG inline)
  • ✅ Grilles flexbox et mises en page multi-colonnes

Pour intégrer le rendu dans votre projet, ajoutez la classe .wysiwyg_view sur le conteneur qui reçoit le HTML, et chargez le CSS KaTeX si des formules mathématiques sont présentes.


<div class="wysiwyg_view">
  
</div>

// PHP
$twig->createTemplate($html);

🌐 Compatibilité

  • ✅ Navigateurs modernes (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+)
  • ✅ Node.js ≥ 18 (SSR : importez, n'instanciez pas côté serveur)
  • ✅ React, Vue, Angular, Svelte — montez editor.el dans un ref/onMount
  • ✅ Vite, Webpack, Rollup, ESBuild
  • ❌ IE11 non supporté

Licence

MIT — Utilisez, modifiez, redistribuez librement.
Code source : github.com/synapxLab/wysiwyg

Rendu en cours…