---
title: "Markdown editor"
type: plugin
version: "2.2.2"
doc_version: "2.7.3"
status: stable
date: 2026-07-05
library: Frutjam
stack: tailwind_css
compatibility: universal
framework_agnostic: true
runtime_requirement: none
description: "JavaScript markdown editor plugin for Tailwind CSS projects. WYSIWYG and plain Markdown modes, live preview, RTL support, dark mode. Works with Django, HTMX, Laravel, React."
url: https://frutjam.com/fr/plugins/markdown-editor
---

# The Native-First, High-Performance Markdown Plugin for JavaScript

## La philosophie : « Les autochtones d'abord »

La plupart des éditeurs rompent avec le flux de travail Web standard. **MarkdownEditor** l’adopte.
Parce qu'il se trouve directement au-dessus d'un `<textarea>`, vous n'avez pas besoin d'apprendre une nouvelle façon de gérer les données.

- **Aucune liaison de données nécessaire :** Fonctionne avec `<form method="POST">` prêt à l'emploi
- **Accès standard :** Utilisez `document.getElementById('editor').value` comme une entrée normale.
- **Agnostique du backend :** fonctionne avec n'importe quel backend (Python, Node.js, PHP, etc.), tout comme un champ de formulaire normal

## Principales fonctionnalités

### 🖼️ Téléchargement d'images avancé (optimisé pour le référencement)

Ne surchargez pas votre base de données avec des chaînes Base64 lourdes. Configurez notre API pour télécharger des images directement sur votre serveur ou votre bucket S3. L'éditeur reçoit l'URL, gardant vos fichiers Markdown légers et le classement SEO de votre site élevé.

### 🔀 Modes hybride et simple

Offrez à vos utilisateurs le meilleur des deux mondes. Basculez entre un **mode hybride visuel (WYSIWYG)** pour un formatage facile et un **mode Markdown simple** pour une édition de syntaxe brute et sans distraction.

### 🌍 Prêt pour le monde entier avec support RTL

Prise en charge native complète des langues de droite à gauche (RTL). Idéal pour les projets nécessitant une prise en charge **de l'arabe, de l'ourdou ou du farsi** avec un alignement automatique de la direction du texte.

### ⚡ Performances à grande échelle

- **Léger** : une petite empreinte d'environ 116 Ko qui ne ralentira pas le chargement de votre page
- **Prise en charge des documents volumineux** : optimisé pour gérer des milliers de lignes de texte sans décalage d'entrée ni gel du navigateur
- **Rendu intelligent** : mises à jour d'aperçu anti-rebond, calculs de style mis en cache et gestion du clavier sans conflit entre la continuation de la liste et l'indentation : Tab et Entrée font toujours exactement une chose.

### ♿ Accessible par défaut

La prise en charge complète d'ARIA est intégrée et ne nécessite aucune configuration supplémentaire. La barre d'outils est un véritable point de repère `role="toolbar"`, le volet d'aperçu est étiqueté `role="region"`, toutes les icônes SVG sont cachées aux lecteurs d'écran, la bascule d'aperçu expose son état activé/désactivé via `aria-pressed`, et les boutons désactivés de la barre d'outils utilisent à la fois `disabled` et `aria-disabled` afin que la technologie d'assistance ne soit jamais induite en erreur. Les modaux renvoient le focus sur le bouton de déclenchement lorsqu'ils sont fermés.

### 🛡️ Zéro conflit CSS

Tous les styles d'éditeur sont entièrement limités à l'élément `.markdown-editor-wrapper`. Le contrôle en amont global de Tailwind (réinitialisation des éléments pour `h1`–`h6`, `a`, `button`, etc.) est exclu, de sorte que l'éditeur peut vivre aux côtés de Bootstrap, Tailwind ou de tout autre framework CSS sur la même page sans casser un seul style.

### 🔒 Aperçu sécurisé XSS

L'aperçu rendu est nettoyé via [DOMPurify](https://github.com/cure53/DOMPurify) avant d'être écrit dans le DOM. Les balises de script, les gestionnaires d'événements en ligne et les URL malveillantes dans les entrées de démarques contrefaites sont automatiquement supprimés — aucune configuration n'est requise.

## Démo de l'éditeur Markdown

# Markdown Editor

## Mise en œuvre rapide

### 1.Installation

Vous pouvez l'installer à l'aide de NPM, importer le fichier JavaScript directement ou utiliser un CDN pour un déploiement rapide.

#### Installer via NPM

```bash
npm install markdown-text-editor
```

OU

#### Utiliser un CDN

Vous pouvez également inclure les liens CDN suivants dans votre HTML

```html
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
```

### 2. La structure HTML

Placez simplement un `<textarea>` dans votre formulaire standard. Aucun emballage spécial requis.

```html
<form action="/api/save" method="POST">
  <textarea id="markdown-editor" name="content"># Hello World</textarea>
  <button type="submit">Save Content</button>
</form>
```

### 3. Importez JS et CSS et initialisez le plugin sur votre élément textarea

```javascript
import MarkdownEditor from "markdown-text-editor";

const editor = new MarkdownEditor('#markdown-editor', {
  placeholder: 'Write your markdown...',
  toolbar: ['heading', 'bold', 'italic', 'strikethrough', 'ul', 'ol', 'checklist', 'blockquote', 'link', 'preview'],
});
```

### 4. Configuration et personnalisation

Vous pouvez entièrement personnaliser le comportement et l'interface de l'éditeur en passant un objet `options`. Si vous omettez une option, la valeur **par défaut** est utilisée.

| Propriété     | Taper            | Défaut           | Purpose                                                                                                                                                                                                  |
| ------------- | ---------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mode`        | `string`         | `'plain'`        | Définit la vue initiale. Utilisez `'hybrid'` pour une expérience WYSIWYG ou `'plain'` pour une syntaxe brute.                                                                                            |
| `placeholder` | `string`         | `'Write...'`     | Texte affiché lorsque l'éditeur est vide.                                                                                                                                                                |
| `toolbar`     | `array`          | `[...]`          | Définit quels outils apparaissent et dans quel ordre.                                                                                                                                                    |
| `footer`      | `false | object` | tout est visible | Contrôle la barre d'état affichée sous l'éditeur. Définissez sur `false` pour le masquer entièrement, ou transmettez un objet pour basculer les statistiques individuelles.                              |
| `theme`       | `string`         | hérité           | Définit explicitement le thème de l'éditeur (`'light'`, `'dark'`, `'snowberry'`, `'darkberry'`). En cas d'omission, l'éditeur hérite du `data-theme` de l'élément ancêtre le plus proche ou du `<textarea>` lui-même. |
| `minHeight`   | `number`         | `200`            | Hauteur minimale en pixels à laquelle l'éditeur se réduira lorsque le contenu est court. S'associe à `maxHeight` pour définir la plage de croissance automatique.                                        |
| `maxHeight`   | `number`         | `500`            | Hauteur maximale en pixels que l'éditeur peut atteindre en mode non plein écran. Une fois que le contenu dépasse cette hauteur, une barre de défilement apparaît dans l'éditeur. L'éditeur dispose également d'une poignée de déplacement permettant aux utilisateurs de le redimensionner manuellement au-delà de cette limite. |
| `onChange`    | `function`       | `undefined`      | Rappel déclenché à chaque modification de contenu : saisie, actions de la barre d'outils, annulation/rétablissement et continuation de la liste. Reçoit la chaîne de démarque actuelle comme seul argument. |

#### 🛠 Personnalisation de la barre d'outils

La barre d'outils est modulaire. Vous pouvez créer une expérience minimale ou une suite de puissance complète en modifiant la baie.

##### Outils disponibles

| Catégorie   | Clés d'outils                                              |
| ----------- | ---------------------------------------------------------- |
| Typographie | `heading`, `bold`, `italic`, `strikethrough`, `blockquote` |
| Listes      | `ul` (balle), `ol` (numéroté), `checklist`                 |
| Code        | `code` (en ligne), `codeblock` (bloc clôturé)              |
| Insertions  | `hr` (règle horizontale), `table` (modèle de tableau)      |
| Médias      | `link`, `image`                                            |
| Édition     | `undo`, `redo`, `indent`, `outdent`                        |
| Voir        | `preview`                                                  |

###### 💡 Conseils de mise en œuvre :

- **Réorganisation** : les boutons apparaissent dans l'ordre exact dans lequel vous les répertoriez dans le tableau.
- **Suppression** : omettez simplement toute clé (comme `image`) du tableau pour désactiver entièrement cette fonctionnalité pour l'utilisateur.
- **Native Fallback** : si vous ne fournissez pas d'`placeholder` dans JS, le plugin utilisera automatiquement l'attribut `placeholder` de votre HTML `<textarea>`

#### 📊 Pied de page (barre d'état)

Le pied de page se trouve sous l'éditeur et affiche la **ligne** du curseur, la **colonne**, le **nombre de caractères** du document et éventuellement le **nombre de mots**, le tout mis à jour en temps réel. Il est visible par défaut et chaque statistique peut être basculée indépendamment.

| Clé     | Taper     | Défaut  | Description                                                                                |
| ------- | --------- | ------- | ------------------------------------------------------------------------------------------ |
| `line`  | `boolean` | `true`  | Afficher le numéro de ligne actuel.                                                        |
| `col`   | `boolean` | `true`  | Afficher le numéro de colonne actuel.                                                      |
| `chars` | `boolean` | `true`  | Afficher le nombre total de caractères.                                                    |
| `words` | `boolean` | `false` | Afficher le nombre total de mots. Désactivé par défaut : défini sur `true` pour l'activer. |

##### Exemples d'utilisation

```javascript
// Default — line, col, and chars visible
new MarkdownEditor('#editor');

// Disable the footer entirely
new MarkdownEditor('#editor', { footer: false });

// Hide only character count
new MarkdownEditor('#editor', { footer: { chars: false } });

// Hide line and column, keep character count
new MarkdownEditor('#editor', { footer: { line: false, col: false } });

// Show only line number
new MarkdownEditor('#editor', { footer: { col: false, chars: false } });

// Enable word count alongside the defaults
new MarkdownEditor('#editor', { footer: { words: true } });

// Show word count only
new MarkdownEditor('#editor', { footer: { line: false, col: false, chars: false, words: true } });
```

### 5. Obtenir, définir et soumettre du contenu

L'un des principaux atouts de **MarkdownEditor** est qu'il maintient le `<textarea>` sous-jacent parfaitement synchronisé. Que vous utilisiez un framework JavaScript moderne ou un backend traditionnel comme **Django, PHP ou Laravel**, le workflow reste simple et natif.

#### 1. La méthode autochtone (recommandée)

Étant donné que l'éditeur améliore une zone de texte standard, vous pouvez utiliser les méthodes DOM familières. C'est le moyen le plus rapide d'interagir avec vos données sans apprendre une nouvelle API.

```javascript
// Retrieve content via ID
const markdown = document.getElementById('markdown-editor').value;

// Set content via ID (The editor UI updates automatically)
document.getElementById('markdown-editor').value = "# New Heading Content";
```

#### 2. Utilisation d'une référence de variable

Si vous avez une référence à l’élément textarea, vous pouvez l’utiliser directement – ​​aucune API spécifique à la bibliothèque n’est nécessaire.

```javascript
const textarea = document.getElementById('markdown-editor');

// Retrieve content
const markdown = textarea.value;

// Set content (the editor UI reflects this immediately)
textarea.value = "## Updated via JS";
```

#### 3. Définition et lecture du contenu

La méthode recommandée pour définir le contenu initial est directement dans le HTML `<textarea>` — cela fonctionne naturellement avec tous les frameworks backend (Django, Laravel, Rails, PHP, etc.) et l'éditeur le restitue automatiquement à l'initialisation.

```html
<!-- Recommended: set content server-side -->
<textarea id="markdown-editor"># Hello World</textarea>
```

Pour lire ou mettre à jour le contenu au moment de l'exécution, utilisez la valeur native `textarea`. Appelez `editor.render()` après une mise à jour pour actualiser l'aperçu et la couche hybride.

```javascript
const textarea = document.getElementById('markdown-editor');

// Read
const markdown = textarea.value;

// Update at runtime
textarea.value = '# New content';
editor.render();
```

#### 4. Démolition de l'éditeur — `destroy()`

Appelez `editor.destroy()` pour supprimer le wrapper DOM de l'éditeur et restaurer le `<textarea>` d'origine à sa position dans le document. Utile dans les applications monopage lors du démontage d'une vue.

```javascript
const editor = new MarkdownEditor('#markdown-editor');

// Remove the editor and restore the plain textarea
editor.destroy();
```

##### React aux changements avec `onChange`

Passez un rappel `onChange` pour être averti de chaque changement de contenu. Reçoit la chaîne de démarque actuelle.

```javascript
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        console.log('Content changed:', value.length, 'characters');
    }
});
```

###### Sauvegarde automatique du brouillon avec `localStorage`

Utilisez `onChange` pour enregistrer un brouillon à chaque frappe. Restaurez-le en pré-remplissant la zone de texte avant d'initialiser l'éditeur.

```javascript
const DRAFT_KEY = 'my-page-draft';

// Restore saved draft before init (only if textarea starts empty)
const textarea = document.getElementById('markdown-editor');
const saved = localStorage.getItem(DRAFT_KEY);
if (saved && !textarea.value) textarea.value = saved;

// Save on every change
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        localStorage.setItem(DRAFT_KEY, value);
    }
});

// Clear draft after successful form submission
document.querySelector('form').addEventListener('submit', () => {
    localStorage.removeItem(DRAFT_KEY);
});
```

#### 4. Soumission automatique de formulaires sans effort

Étant donné que **MarkdownEditor** est construit directement sur le `<textarea>` natif, il est compatible avec tous les frameworks backend (Django, Laravel, PHP, Ruby on Rails, etc.) dès la sortie de la boîte.

C'est là que brille la philosophie « Native-First ». Vous n'avez pas besoin de synchroniser manuellement les données avant de soumettre un formulaire. Le navigateur traite l'éditeur exactement comme un champ de saisie standard.

```html
<form method="POST" action="/api/submit">
  <textarea id="markdown-editor" name="content" class="h-48" rows="5">
    # Initial Content
  </textarea>

  <button type="submit">Submit to Server</button>
</form>

<script>
  // Just initialize it. That's it.
  new MarkdownEditor('#markdown-editor');
</script>
```

**Remarque :** Initialisation du plugin MarkdownEditor obligatoire

Utilisez simplement un `<form>` HTML standard. L'attribut `name` sur la zone de texte est ce que votre serveur utilisera pour identifier le contenu.

##### 🚀 Pourquoi cela change la donne pour les backends

Étant donné que l'éditeur préserve le comportement natif `<textarea>`, votre serveur gère les données comme une chaîne standard. Aucune logique supplémentaire n'est requise : pas de `preventDefault()` ni de construction manuelle `FormData`.

##### 💡 Pourquoi s'agit-il d'une « fonctionnalité qui tue » :

La plupart des éditeurs (comme Quill, Editor.js, simpleMDE, easyMDE) enregistrent les données dans des structures JSON complexes. Si un développeur les utilise, il doit réécrire son schéma de base de données et sa logique de rendu.

Avec **MarkdownEditor**, un développeur peut prendre un ancien site Web, remplacer un simple `<textarea>` par votre éditeur, et le **backend ne sait même pas qu'il a changé**. Il reçoit simplement le même texte brut qu’il a toujours reçu, mais l’utilisateur bénéficie d’une expérience 10 fois meilleure.

| Cadre / Langage   | Comment accéder au contenu Markdown |
| ----------------- | ----------------------------------- |
| PHP               | $\_POST['content']                  |
| Django            | request.POST.get('content')         |
| Node.js (Express) | req.body.content                    |
| Laravel           | $request->input('content')          |
| Ruby on Rails     | params[:content]                    |

## Options de configuration

### 🖼️ Téléchargement avancé d'images

La gestion native des téléchargements d'images, plutôt que de s'appuyer sur des chaînes Base64 lentes et gourmandes en mémoire, constitue un gain significatif en termes de performances et de référencement.

#### Options de configuration

L'outil d'image prend en charge une configuration `fileInput` pour gérer les téléchargements directs sur le serveur.

- `accepter` : définir un tableau de formats d'image autorisés (par exemple, 'webp', 'avif')
- `uploadUrl` : spécifiez le point de terminaison backend où l'objet `File` sera envoyé via `POST`
- `params` : objet facultatif pour envoyer des données supplémentaires (telles que des jetons CSRF, des identifiants utilisateur ou des noms de dossier) à côté du fichier image

#### Exemple d'utilisation (configuration complète)

```javascript
const options = {
  placeholder: 'Start writing...',
  toolbar: [
    'link',
    {
      image: {
        fileInput: {
            accept: ['webp', 'avif'], // restrict the image upload format
            uploadUrl: '/api/upload', // Your upload endpoint
            params: {
                _token: 'your_csrf_token_here', // Essential for Laravel/Django
                folder: 'blog_posts'
            }
        },
        // Supports boolean: true/false OR object: { required: true }
        altInput: { required: true }
      }
    },
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);
```

#### 📡 Détails de l'intégration du serveur

##### 1. La demande

L'éditeur envoie une requête `POST` sous la forme `multipart/form-data`. Par défaut, il comprend :

- `image_file` : l'objet fichier réel
- `image_alt` : Le texte alternatif saisi par l'utilisateur
- ...plus toutes les données personnalisées définies dans l'objet `params`

##### 2. La réponse requise

Pour confirmer un téléchargement réussi et insérer l'image dans l'éditeur, votre serveur **doit** renvoyer la structure JSON suivante :

```json
{
  "success": true,
  "image_path": "https://cdn.yourdomain.com/uploads/image.webp"
}
```

**Remarque** : Assurez-vous d'utiliser la clé `image_path` pour l'URL de l'image téléchargée.

#### Validation du texte alternatif de l'image (`altInput`)

Pour garantir que votre contenu reste accessible et optimisé pour le référencement, `MarkdownEditor` applique la validation du texte alternatif par défaut. Vous pouvez configurer ce comportement à l'aide d'un raccourci booléen ou d'un objet détaillé.

- **Comportement par défaut** : si `altInput` n'est pas défini, il est par défaut `{ obligatoire : vrai `
- **Appliquer l'accessibilité** : les utilisateurs ne pourront pas insérer d'image tant qu'une description alternative n'est pas fournie.

##### Exemples de configuration :

###### 1. Par défaut (aucune configuration requise)

```javascript
// Alt text is REQUIRED by default
image: {
  fileInput: { uploadUrl: '/api/upload' }
}
```

###### 2. Raccourci (désactiver la validation)

Si vous souhaitez autoriser les images sans description, définissez simplement le booléen sur `false`.

```javascript
image: {
  altInput: false // Users can now skip the alt text field
}
```

###### 3. Basé sur des objets (explicite)

```javascript
image: {
    altInput: {
        required: false // Disables alt text validation — users can skip the alt field
    }
}
```

#### Utilisation d'image standard (pas de `fileInput`) :

Si `fileInput` n'est pas configuré, l'éditeur utilise par défaut un simple modal basé sur une URL. C’est idéal si vos utilisateurs établissent principalement des liens vers des hôtes d’images externes.

```javascript
const options = {
  toolbar: [
    'link',
    'image',
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);
```

##### 💡 Pourquoi utiliser des paramètres ?

Dans des frameworks comme Laravel ou Django, vous ne pouvez pas télécharger de fichiers sans jeton CSRF. En ajoutant `_token` à l'objet `params`, votre requête passera de manière transparente par le middleware de sécurité du backend, conservant ainsi la philosophie « Zéro logique » pour vos contrôleurs côté serveur.

### 🔀 Modes d'édition

**MarkdownEditor** propose deux manières distinctes d'écrire et de formater votre contenu. Vous pouvez basculer entre une vue traditionnelle axée sur la syntaxe ou une expérience moderne axée avant tout sur le visuel.

#### Configuration

Vous pouvez définir le mode de démarrage à l'aide de la propriété `mode` lors de l'initialisation.

- `plain` (**Default**) : un environnement Markdown propre et performant où la syntaxe (comme `**bold**` ou `# head`) est visible. Idéal pour les développeurs et les puristes de Markdown
- `hybride` : une expérience inspirée de WYSIWYG qui restitue le formatage (gras, italique, titres) en temps réel au fur et à mesure que vous tapez, tout en conservant la structure Markdown sous-jacente.

##### Mise en œuvre:

```javascript
// Default initialization (Plain Mode)
new MarkdownEditor('#markdown-editor');

// Explicit Plain Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'plain'
});

// Hybrid (Visual) Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid'
});
```

##### Aperçu des modes hybride et simple :

###### Hybrid Mode

Le formatage visuel est rendu en temps réel pendant que vous tapez.

# Hybrid mode markdown editor
This will render visual styles immediately.

###### Mode simple (par défaut)

Se concentre sur la syntaxe Markdown brute pour une expérience légère.

# Plain mode markdown editor
This shows the raw **syntax**.

| Configuration                                                                                                                                                                                            | Propriété / Outil                                                                                                                                                                                        | Description                                                                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Objet Options                                                                                                                                                                                            | `placeholder`                                                                                                                                                                                            | Définit le texte d'espace réservé pour la zone de texte (facultatif, car vous pouvez également utiliser l'attribut HTML textarea standard)                                                               |
|                                                                                                                                                                                                          | `mode: 'hybrid'`                                                                                                                                                                                         | Permet une expérience inspirée de WYSIWYG qui restitue le formatage (gras, italique, titres) en temps réel au fur et à mesure que vous tapez.                                                            |
| `barre d'outils` : Détermine quels outils    apparaissent dans la barre d'outils et leur ordre.                                                                                                          | `heading`                                                                                                                                                                                                | Ouvre une liste déroulante pour sélectionner les niveaux de titre H1 à H6                                                                                                                                |
|                                                                                                                                                                                                          | `bold`                                                                                                                                                                                                   | Active le formatage du texte en gras.                                                                                                                                                                    |
|                                                                                                                                                                                                          | `italic`                                                                                                                                                                                                 | Active le formatage du texte en italique.                                                                                                                                                                |
|                                                                                                                                                                                                          | `strikethrough`                                                                                                                                                                                          | Permet le texte barré.                                                                                                                                                                                   |
|                                                                                                                                                                                                          | `ol`                                                                                                                                                                                                     | (Liste ordonnée) : convertit le texte en un format de liste numérotée.                                                                                                                                   |
|                                                                                                                                                                                                          | `ul`                                                                                                                                                                                                     | (Liste non ordonnée) : convertit le texte en liste à puces.                                                                                                                                              |
|                                                                                                                                                                                                          | `checklist`                                                                                                                                                                                              | Ajoute des cases à cocher à votre texte, ce qui le rend idéal pour les tâches, les listes de tâches ou le suivi de l'état d'avancement.                                                                  |
|                                                                                                                                                                                                          | `blockquote`                                                                                                                                                                                             | Mettez en surbrillance le texte cité ou souligné.                                                                                                                                                        |
|                                                                                                                                                                                                          | `code`                                                                                                                                                                                                   | Encapsule le texte sélectionné dans des backticks simples pour le code en ligne. Cliquer à nouveau supprime les backticks.                                                                               |
|                                                                                                                                                                                                          | `codeblock`                                                                                                                                                                                              | Encapsule le texte sélectionné dans un bloc de code clôturé à triple backtick. Un nouveau clic supprime les clôtures.                                                                                    |
|                                                                                                                                                                                                          | `hr`                                                                                                                                                                                                     | Insère une règle horizontale `---` à la position du curseur sur sa propre ligne.                                                                                                                         |
|                                                                                                                                                                                                          | `table`                                                                                                                                                                                                  | Insère un modèle de tableau de démarques de départ 2x3 à la position du curseur.                                                                                                                         |
|                                                                                                                                                                                                          | `image`                                                                                                                                                                                                  | Vous permet d'insérer des images via la syntaxe markdown.                                                                                                                                                |
|                                                                                                                                                                                                          | `link`                                                                                                                                                                                                   | Vous permet d'ajouter des hyperliens à votre texte.                                                                                                                                                      |
|                                                                                                                                                                                                          | `undo`                                                                                                                                                                                                   | Pour annuler les dernières modifications.                                                                                                                                                                |
| `redo`                                                                                                                                                                                                   | Pour réappliquer les dernières modifications annulées.                                                                                                                                                   |
| `indent`                                                                                                                                                                                                 | Pour augmenter le niveau d'indentation.                                                                                                                                                                  |
| `outdent`                                                                                                                                                                                                | Pour diminuer le niveau d'indentation.                                                                                                                                                                   |
| `preview`                                                                                                                                                                                                | Active/désactive un aperçu côte à côte en plein écran. Les cases à cocher dans le volet d'aperçu sont cliquables et mettent à jour instantanément la source de démarque. Appuyez sur Échap pour quitter le plein écran. |
| [**Fonctionnalité avancée de téléchargement d'images**](#advanced-image-upload) :    Permet de configurer les téléchargements d'images sur votre propre serveur et de définir le chemin d'accès de l'image via une API. Cela améliore les performances et le référencement. | `fileInput`                                                                                                                                                                                              | `accepter` : tableau de types de fichiers image autorisés (par exemple `'webp'`, `'avif'`).   `uploadUrl` : point de terminaison backend où le fichier est envoyé via `POST`.   `params` : objet facultatif pour les données supplémentaires (jetons CSRF, identifiants utilisateur, noms de dossiers) |
|                                                                                                                                                                                                          | `altInput`                                                                                                                                                                                               | `obligatoire : false` : désactive la validation de l'entrée de texte alternatif (la valeur par défaut est true)                                                                                          |

### ⌨️ Raccourcis clavier

Les actions de formatage courantes peuvent être déclenchées directement depuis le clavier sans toucher à la barre d'outils. Chaque raccourci est également affiché dans l'info-bulle du bouton de la barre d'outils correspondant.

| Raccourci                    | Action                                                    |
| ---------------------------- | --------------------------------------------------------- |
| `Ctrl + B` / `⌘ B`           | Activer le **Gras**                                       |
| `Ctrl + I` / `⌘ I`           | Activer l'option *Italique*                               |
| `Ctrl + K` / `⌘ K`           | Insérer un lien                                           |
| `` Ctrl + ` `` / `` ⌘ ` ``   | Basculer le `Code` en ligne                               |
| `Ctrl + Shift + S` / `⌘ ⇧ S` | Activer l'option ~~Barré~~                                |
| `Ctrl + Z` / `⌘ Z`           | Défaire                                                   |
| `Ctrl + Shift + Z` / `⌘ ⇧ Z` | Refaire                                                   |
| `Tab`                        | Indenter les lignes sélectionnées                         |
| `Shift + Tab`                | Supprimer les lignes sélectionnées                        |
| `Ctrl + F` / `⌘ F`           | Ouvrir le panneau Rechercher                              |
| `Ctrl + H` / `⌘ H`           | Ouvrir le panneau Rechercher et remplacer                 |
| `Escape`                     | Fermer le panneau Rechercher/Quitter l’aperçu plein écran |

### 🔍 Trouvez etamp; Remplacer

Un panneau de recherche et de remplacement intégré est disponible dans l’éditeur – aucune extension de navigateur ni outil séparé n’est nécessaire.

- Appuyez sur `Ctrl + F` (ou `⌘ F`) pour ouvrir le panneau **Rechercher**.
- Appuyez sur `Ctrl + H` (ou `⌘ H`) pour ouvrir la fenêtre **Rechercher et amp; Remplacer le panneau**
- La recherche ne respecte pas la casse et affiche un compteur de correspondances en direct (par exemple, *3 sur 12*).
- Parcourez les correspondances avec les boutons **▲ / ▼** ou `Entrée` / `Maj + Entrée`
- **Remplacer** remplace la correspondance actuelle en surbrillance ; **Remplacer tout** remplace chaque occurrence à la fois
- Appuyez sur `Échap` pour fermer le panneau et redonner le focus à l'éditeur.

Le panneau flotte dans le coin supérieur droit de la zone de contenu de l'éditeur et n'interrompt pas l'écriture.

### 🌙 Thématisation

**MarkdownEditor** hérite automatiquement de son thème de la page environnante — aucune configuration n'est requise. L'éditeur lit le `data-theme` de l'ancêtre le plus proche lors de l'initialisation, il reste donc synchronisé avec le thème de votre site dès la sortie de la boîte.

#### Comment le thème est résolu (ordre de priorité)

1. Option **`theme`** — remplacement explicite transmis dans l'objet options
2. **`data-theme` sur le `<textarea>`** — défini directement sur l'élément
3. **`data-theme` sur n'importe quel ancêtre** — par ex. `<html>`, `<body>` ou un wrapper `<div>`

#### Thèmes disponibles

`'light'` (par défaut), `'dark'`, `'snowberry'`, `'darkberry'`

##### Option 1 : hériter de `<html>` ou de tout ancêtre (zéro configuration)

```html
<html data-theme="dark">
  ...
  <textarea id="markdown-editor"></textarea>
  <script>
    new MarkdownEditor('#markdown-editor'); // picks up dark automatically
  </script>
```

##### Option 2 : définissez le `data-theme` directement sur le `<textarea>`

```html
<textarea id="markdown-editor" data-theme="dark"></textarea>
<script>
  new MarkdownEditor('#markdown-editor');
</script>
```

##### Option 3 — option explicite `theme` (remplace tout)

```javascript
new MarkdownEditor('#markdown-editor', {
    theme: 'dark'
});
```

#### 🎨 Thème personnalisé via des variables CSS

Vous pouvez entièrement personnaliser l'apparence de l'éditeur en remplaçant ses variables CSS sur l'élément `.markdown-editor-wrapper` ou n'importe quel sélecteur `[data-theme]`. Toutes les couleurs utilisent l'[espace colorimétrique OKLCH](https://oklch.com) pour des résultats perceptuellement uniformes.

| Variable             | Purpose                                                   | Lumière par défaut      | Sombre par défaut       |
| -------------------- | --------------------------------------------------------- | ----------------------- | ----------------------- |
| `--color-base`       | Contexte de l'éditeur                                     | `oklch(100% 0 0)`       | `oklch(10.9% 0 0)`      |
| `--color-on-base`    | Couleur du texte principal                                | `oklch(22% 0 0)`        | `oklch(98% 0 0)`        |
| `--color-primary`    | Accent principal (barre d'outils active, liens)           | `oklch(51.1% .262 277)` | `oklch(66.4% .184 286)` |
| `--color-on-primary` | Texte sur des surfaces de couleurs primaires              | `oklch(96.2% .018 272)` | `oklch(10% .01 270)`    |
| `--color-secondary`  | Accent secondaire                                         | `oklch(59.1% .293 323)` | `oklch(65% .18 220)`    |
| `--color-accent`     | Mettre l'accent en surbrillance (code en ligne, italique) | `oklch(54.1% .281 293)` | `oklch(75% .18 50)`     |
| `--color-neutral`    | Surfaces neutres (bordures, séparateurs)                  | `oklch(15% 0 0)`        | `oklch(85% 0 0)`        |
| `--color-error`      | Couleur de l'état d'erreur                                | `oklch(57.7% .245 27)`  | `oklch(60% .22 30)`     |
| `--border-radius`    | Arrondi des coins du cadre de l'éditeur                   | `0.25rem`               | |

##### Exemple de thème personnalisé

Remplacez n'importe quelle variable sur `.markdown-editor-wrapper` après l'initialisation de l'éditeur, ou définissez un bloc `[data-theme]` personnalisé dans votre feuille de style :

```css
/* Override individual variables */
.markdown-editor-wrapper {
    --color-primary: oklch(60% 0.2 30);   /* orange accent */
    --border-radius: 0.5rem;
}

/* Or define a full custom theme */
[data-theme="brand"] .markdown-editor-wrapper,
.markdown-editor-wrapper[data-theme="brand"] {
    --color-base:       oklch(15% 0.01 250);
    --color-on-base:    oklch(95% 0 0);
    --color-primary:    oklch(65% 0.22 145);   /* green */
    --color-on-primary: oklch(10% 0 0);
    --color-accent:     oklch(75% 0.18 60);
    --color-neutral:    oklch(80% 0 0);
    --border-radius:    0.75rem;
}
```

```javascript
new MarkdownEditor('#markdown-editor', { theme: 'brand' });
```

- **Aperçu en temps réel** : consultez votre démarque instantanément au fur et à mesure que vous tapez.
- **Surlignage de la syntaxe** : lisibilité améliorée grâce à un code clair et un formatage markdown.
- **Intégration facile** : intégration transparente dans n'importe quel projet Web avec une configuration minimale.
- **Barre d'outils personnalisable :** configurez et réorganisez dynamiquement les options de la barre d'outils comme le gras, l'italique, etc.

## Caractéristiques

## 🔌 Intégration de formulaire natif

Fonctionne exactement comme un `<textarea>` standard. Pas d'API complexe : utilisez simplement l'attribut `value` ou `name`. Cela "fonctionne simplement" avec les soumissions de formulaires HTML standard en PHP, Django ou Node.js.

## 🖼️ Téléchargement d'images avancé

Configurez les téléchargements de serveur natifs via l'API. Évitez les chaînes Base64 lourdes pour garantir des chargements de pages plus rapides et un référencement supérieur en hébergeant des images sur votre propre CDN.

## 🔀 Modes hybride et simple

Basculez entre une expérience **Hybride (WYSIWYG)** pour l'édition visuelle ou le mode **Plain Markdown** pour une sensation de codage traditionnelle.

## 🚀 Hautes performances

Un petit bundle **~116 Ko** optimisé pour le "contenu lourd". Gère des documents volumineux et des fichiers volumineux sans aucun décalage d’entrée ni baisse de performances.

## 🌍 Prise en charge RTL intégrée

Prise en charge native des langues de droite à gauche comme l'arabe, l'ourdou et le farsi. Parfait pour créer des applications accessibles à l’échelle mondiale.

## 🌙 Thématisation adaptative

Inclut la prise en charge automatique du mode sombre. Il se synchronise avec les paramètres de votre système ou avec la bibliothèque **Frutjam UI** pour une expérience visuelle fluide.

## 📝 Édition intelligente

Suite automatique de liste de style GitHub pour les listes ordonnées, les listes non ordonnées et les listes de contrôle : appuyez sur `Entrée` et l'éditeur continue le modèle. Les cases à cocher dans le volet d'aperçu sont cliquables et se synchronisent instantanément avec la source de démarque.

## 📱 Entièrement réactif

Une interface utilisateur fluide et mobile qui s'adapte parfaitement aux ordinateurs de bureau, aux tablettes et aux smartphones pour une édition en déplacement.

## 📦 Assistance universelle

Compatible avec **ESM, UMD, CommonJS et IIFE**. Fonctionne immédiatement via CDN (`<script src>`), npm ou tout autre bundler (Vite, webpack, Rollup) — aucune configuration supplémentaire n'est nécessaire.

## ♿ Accessible par défaut

Prise en charge complète d'ARIA intégrée : repère de la barre d'outils, région d'aperçu étiquetée, boutons conviviaux pour les lecteurs d'écran, `aria-pressed` sur la bascule d'aperçu, `disabled` et `aria-disabled` sur les outils inactifs et correction de la restauration du focus à la fermeture des modaux.

## 🛡️ Zéro conflit CSS

Les styles d'éditeur s'étendent entièrement à `.markdown-editor-wrapper`. Le contrôle en amont global de Tailwind est exclu afin que l'éditeur vive en toute sécurité aux côtés de Bootstrap, Tailwind ou de tout autre framework sans rompre leurs styles.

## ⌨️ Raccourcis clavier

`Ctrl+B`, `Ctrl+I`, `Ctrl+K`, `` Ctrl+` ``, `Ctrl+Shift+S` — actions de formatage courantes sans toucher la souris. Chaque raccourci est affiché dans l'info-bulle du bouton de la barre d'outils.

## 🔍 Trouvez etamp; Remplacer

Appuyez sur `Ctrl+F` pour rechercher ou sur `Ctrl+H` pour ouvrir Rechercher & remplacer. Recherche insensible à la casse avec compteur de correspondances en direct, navigation suivant/précédent, remplacement unique et tout remplacement, sans quitter l'éditeur.

## Exemple de configuration complète

Utilisez cet exemple complet pour initialiser **MarkdownEditor** avec toutes les fonctionnalités principales, y compris l'ordre des barres d'outils personnalisées et la gestion avancée du téléchargement d'images.

```javascript
const editor = new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid',
    placeholder: 'Start writing...',
    footer: {
        line: true,
        col: true,
        chars: true,
        words: true,
    },
    onChange(value) {
        console.log('Content updated:', value.length, 'characters');
    },
    toolbar: [
        'heading', 'bold', 'italic', 'strikethrough', 'blockquote',
        'ul', 'ol', 'checklist',
        'code', 'codeblock', 'hr', 'table',
        {
            image: {
                fileInput: {
                    accept: ['webp', 'avif', 'png'],
                    uploadUrl: '/api/upload'
                }
            }
        },
        'link', 'undo', 'redo', 'indent', 'outdent', 'preview'
    ],
});

// Read content natively
const markdown = document.getElementById('markdown-editor').value;

// Update content programmatically (dispatch input to keep preview in sync)
// const ta = document.getElementById('markdown-editor');
// ta.value = '# New content';
// ta.dispatchEvent(new Event('input', { bubbles: true }));

// destroy() when the view unmounts (SPAs)
// editor.destroy();
```

