Ir al contenido principal

El complemento Markdown nativo y de alto rendimiento para JavaScript

Última actualización:

Complemento de edición de texto Markdown que transforma un área de texto nativa en una suite de edición completa, sin necesidad de sincronización. Modos WYSIWYG y Markdown simple, vista previa en vivo, buscar y reemplazar, compatibilidad con RTL, modo oscuro. Funciona con Django, Laravel, Rails, Node.js, PHP y cualquier pila.

La filosofía: "los nativos primero"

La mayoría de los editores rompen el flujo de trabajo web estándar. MarkdownEditor lo acepta. Debido a que se encuentra directamente encima de un <textarea>, no es necesario aprender una nueva forma de manejar los datos.

  • No se necesita enlace de datos: Funciona con <form método="POST"> listo para usar
  • Acceso estándar: Utilice document.getElementById('editor').value como una entrada normal.
  • Agnóstico del backend: funciona con cualquier backend (Python, Node.js, PHP, etc.) como un campo de formulario normal.

MarkdownEditor frente a EasyMDE/SimpleMDE

La mayoría de los editores de rebajas de JavaScript (EasyMDE, SimpleMDE, editores basados ​​en CodeMirror) reemplazan su <textarea> con un elemento personalizado. Eso significa que el envío del formulario se interrumpe, .value no devuelve nada y hay que escribir código adicional solo para volver a leer el contenido. MarkdownEditor es diferente: mejora su área de texto existente y nunca la reemplaza.

Característica Editor de rebajas FácilMDE/SimpleMDE
Área de texto nativa preservada ❌ Reemplazado
El envío de formularios funciona tal cual ❌ Requiere JS adicional
Obtener/establecer valor a través de .value ❌ Se necesita API personalizada
Modo híbrido WYSIWYG
Buscar y reemplazar incorporado
soporte RTL
Compatible con CSP (sin JS en línea)
Cero conflictos CSS
Modo oscuro/temática Limitado
Tamaño del paquete ~116 KB ~300KB+

Integración del marco

Debido a que MarkdownEditor conserva el <textarea> nativo, se integra con cada marco de backend sin ningún código adicional. Su servidor recibe el contenido de rebajas exactamente como lo haría desde cualquier campo de formulario estándar.

Django

Agregue un class a su widget de área de texto e inicialice el editor: request.POST['content'] funciona sin pasos adicionales.

python
1
2
3
4
5
6
7
8
# forms.py
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['content']
        widgets = {
            'content': forms.Textarea(attrs={'class': 'markdown-editor'}),
        }
javascript
1
2
new MarkdownEditor('.markdown-editor');
// request.POST['content'] contains the markdown on submit

Laravel

Utilice f.text_area con una clase: $request->input('content') recibe la rebaja directamente.

html
1
2
<textarea name="content" class="markdown-editor">{{ old('content') }}</textarea>
<script>new MarkdownEditor('.markdown-editor');</script>

Rubí sobre rieles

Funciona con form_with listo para usar: params[:content] contiene la rebaja. Para Turbo Drive, utilice turbo:load en lugar de DOMContentLoaded.

javascript
1
2
3
4
5
6
document.addEventListener('turbo:load', () => {
    document.querySelectorAll('.markdown-editor:not([data-mde-init])').forEach(el => {
        el.setAttribute('data-mde-init', 'true');
        new MarkdownEditor(el);
    });
});

Nodo.js/Expreso

req.body.content recibe la rebaja al enviar el formulario: sin paso de sincronización ni extracción personalizada.

html
1
2
3
<textarea name="content" class="markdown-editor"></textarea>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

PHP

$_POST['content'] funciona exactamente como con cualquier área de texto estándar: colóquelo y el manejo de su formulario existente no requerirá cambios.

html
1
2
3
4
5
6
<form method="POST" action="save.php">
  <textarea name="content" class="markdown-editor"></textarea>
  <button type="submit">Save</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

Características clave

🖼️ Carga de imágenes avanzada (optimizada para SEO)

No infles tu base de datos con cadenas Base64 pesadas. Configure nuestra API para cargar imágenes directamente a su servidor o depósito S3. El editor recibe la URL, lo que mantiene sus archivos Markdown livianos y la clasificación SEO de su sitio alta.

🔀 Modos híbridos y simples

Ofrezca a sus usuarios lo mejor de ambos mundos. Cambie entre un modo híbrido visual (WYSIWYG) para formatear fácilmente y un modo Markdown simple para una edición de sintaxis sin formato y sin distracciones.

🌍 Listo para todo el mundo con soporte RTL

Soporte nativo completo para idiomas de derecha a izquierda (RTL). Perfecto para proyectos que requieren compatibilidad con árabe, urdu o farsi con alineación automática de la dirección del texto.

⚡ Rendimiento a escala

  • Ligero: ocupa un pequeño espacio de ~116 KB que no ralentizará la carga de la página.
  • Compatibilidad con documentos grandes: optimizado para manejar miles de líneas de texto sin retrasos en la entrada ni congelación del navegador.
  • Representación inteligente: actualizaciones de vista previa sin rebote, cálculos de estilo en caché y manejo del teclado sin conflictos entre la continuación de la lista y la sangría, por lo que Tab y Enter siempre hacen exactamente una cosa.

♿ Accesible por defecto

La compatibilidad total con ARIA está integrada y no requiere configuración adicional. La barra de herramientas es un punto de referencia role="toolbar" adecuado, el panel de vista previa tiene la etiqueta role="region", todos los íconos SVG están ocultos para los lectores de pantalla, el interruptor de vista previa expone su estado activado/desactivado a través de aria-pressed y los botones deshabilitados de la barra de herramientas usan tanto disabled como aria-disabled para que la tecnología de asistencia nunca se engañe. Los modales devuelven el foco al botón de activación cuando están cerrados.

🛡️ Cero conflictos de CSS

Todos los estilos del editor tienen un alcance completo en el elemento .markdown-editor-wrapper. La verificación previa global de Tailwind (restablecimientos de elementos para h1h6, a, button, etc.) está excluida, por lo que el editor puede coexistir con Bootstrap, Tailwind o cualquier otro marco CSS en la misma página sin romper un solo estilo.

🔒 Vista previa segura XSS

La vista previa renderizada se desinfecta a través de DOMPurify antes de escribirse en el DOM. Las etiquetas de script, los controladores de eventos en línea y las URL maliciosas en las entradas de rebajas diseñadas se eliminan automáticamente, sin necesidad de configuración.

Demostración del editor de rebajas

Implementación rápida

1. Instalación

NPM (paquetes: Vite, webpack, Rollup, etc.)

bash
npm install markdown-text-editor
javascript
1
2
import MarkdownEditor from 'markdown-text-editor';
new MarkdownEditor('#markdown-editor');

CDN: módulo ES

html
1
2
3
4
<script type="module">
  import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/dist/markdown-text-editor.es.js';
  new MarkdownEditor('#markdown-editor');
</script>

CDN: etiqueta de secuencia de comandos global (IIFE)

No es necesario importar: MarkdownEditor está disponible automáticamente como una variable global.

html
1
2
3
4
5
6
7
8
9
<form action="/api/save" method="POST">
  <textarea id="markdown-editor" name="content"># Hello World</textarea>
  <button type="submit">Save Content</button>
</form>

<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>
  new MarkdownEditor('#markdown-editor');
</script>

2. Configuración e inicialización

Pase un objeto de opciones para personalizar el editor. Todas las opciones son opcionales: omita cualquiera para utilizar el valor predeterminado.

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

¿Disfrutas del editor Markdown?

Tarda 2 segundos y ayuda a que el proyecto crezca. Es parte de Frutjam, una biblioteca gratuita de componentes CSS de Tailwind; una estrella allí también ayuda.

Estrella en GitHub

4. Configuración y personalización

Puede personalizar completamente el comportamiento y la interfaz del editor pasando un objeto options. Si omite una opción, se utiliza el valor predeterminado.

Propiedad Tipo Por defecto Objetivo
mode string 'plain' Establece la vista inicial. Utilice híbrido para una experiencia WYSIWYG o simple para sintaxis sin formato.
placeholder string 'Write...' Texto que se muestra cuando el editor está vacío.
toolbar array [...] Define qué herramientas aparecen y en qué orden.
footer false | object todo visible Controla la barra de estado que se muestra debajo del editor. Configúrelo en false para ocultarlo por completo o pase un objeto para alternar estadísticas individuales.
theme string heredado Establece explícitamente el tema del editor (claro, oscuro, snowberry, darkberry). Si se omite, el editor hereda data-theme del elemento ancestro más cercano o del propio <textarea>.
minHeight number 200 Altura mínima en píxeles a la que se reducirá el editor cuando el contenido sea corto. Se combina con maxHeight para establecer el rango de crecimiento automático.
maxHeight number 500 Altura máxima en píxeles hasta la que el editor puede crecer en modo no de pantalla completa. Una vez que el contenido excede esta altura, aparece una barra de desplazamiento dentro del editor. El editor también tiene un controlador de arrastre para que los usuarios puedan cambiar su tamaño manualmente más allá de este límite.
onChange function undefined La devolución de llamada se activa con cada cambio de contenido: escritura, acciones de la barra de herramientas, deshacer/rehacer y continuación de la lista. Recibe la cadena de rebajas actual como único argumento.

🛠 Personalización de la barra de herramientas

La barra de herramientas es modular. Puede crear una experiencia mínima o un paquete de energía con todas las funciones modificando la matriz.

Herramientas disponibles
Categoría Teclas de herramientas
Tipografía heading, bold, italic, strikethrough, blockquote
Liza ul (bala), ol (numerado), checklist
Código code (en línea), codeblock (bloque cercado)
Insertos hr (regla horizontal), table (plantilla de tabla)
Medios de comunicación link, image
Edición undo, redo, indent, outdent
Vista preview
💡 Consejos de implementación:
  • Reordenamiento: los botones aparecen en el orden exacto en que los enumera en la matriz.
  • Eliminar: simplemente omita cualquier clave (como image) de la matriz para desactivar esa función por completo para el usuario.
  • Reserva nativa: si no proporciona un placeholder en JS, el complemento utilizará automáticamente el atributo placeholder de su HTML <textarea>.

📊 Pie de página (barra de estado)

El pie de página se encuentra debajo del editor y muestra la línea, la columna del cursor, el recuento de caracteres del documento y, opcionalmente, el recuento de palabras, todo actualizado en tiempo real. Es visible de forma predeterminada y cada estadística se puede alternar de forma independiente.

Llave Tipo Por defecto Descripción
line boolean true Muestra el número de línea actual.
col boolean true Muestra el número de columna actual.
chars boolean true Muestra el recuento total de caracteres.
words boolean false Muestra el recuento total de palabras. Desactivado de forma predeterminada: configúrelo en true para habilitarlo.
Ejemplos de uso
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 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. Obtener, configurar y enviar contenido

Una de las principales fortalezas de MarkdownEditor es que mantiene el <textarea> subyacente perfectamente sincronizado. Ya sea que esté utilizando un marco de JavaScript moderno o un backend tradicional como Django, PHP o Laravel, el flujo de trabajo sigue siendo simple y nativo.

1. A la manera nativa (recomendado)

Debido a que el editor mejora un área de texto estándar, puede utilizar métodos DOM familiares. Esta es la forma más rápida de interactuar con sus datos sin necesidad de aprender una nueva API.

javascript
1
2
3
4
5
// 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. Usando una referencia variable

Si tiene una referencia al elemento de área de texto, puede usarla directamente; no se necesita una API específica de la biblioteca.

javascript
1
2
3
4
5
6
7
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. Configuración y lectura de contenido

La forma recomendada de configurar el contenido inicial es directamente en el HTML <textarea>; esto funciona de forma natural con todos los frameworks backend (Django, Laravel, Rails, PHP, etc.) y el editor lo representa automáticamente en el inicio.

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

Para leer o actualizar contenido en tiempo de ejecución, utilice el valor nativo textarea. Llame a editor.render() después de una actualización para actualizar la vista previa y la capa híbrida.

javascript
1
2
3
4
5
6
7
8
const textarea = document.getElementById('markdown-editor');

// Read
const markdown = textarea.value;

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

4. Derribar el editor: destroy()

Llame a editor.destroy() para eliminar el contenedor DOM del editor y restaurar el <textarea> original a su posición en el documento. Útil en aplicaciones de una sola página al desmontar una vista.

javascript
1
2
3
4
const editor = new MarkdownEditor('#markdown-editor');

// Remove the editor and restore the plain textarea
editor.destroy();
React a los cambios con onChange

Pase una devolución de llamada onChange para recibir notificaciones sobre cada cambio de contenido. Recibe la cadena de rebajas actual.

javascript
1
2
3
4
5
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        console.log('Content changed:', value.length, 'characters');
    }
});
Borrador de guardado automático con localStorage

Utilice onChange para guardar un borrador con cada pulsación de tecla. Restáurelo completando previamente el área de texto antes de inicializar el editor.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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. Envío automático de formularios sin esfuerzo

Debido a que MarkdownEditor está construido directamente en el <textarea> nativo, es compatible con todos los frameworks backend (Django, Laravel, PHP, Ruby on Rails, etc.) desde el primer momento.

Aquí es donde brilla la filosofía de "los nativos primero". No es necesario sincronizar datos manualmente antes de enviar un formulario. El navegador trata al editor exactamente como un campo de entrada estándar.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<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>

Nota: La inicialización del complemento MarkdownEditor es obligatoria

Simplemente utilice un HTML estándar <form>. El atributo name en el área de texto es lo que su servidor utilizará para identificar el contenido.

🚀 Por qué cambia las reglas del juego para los backends

Dado que el editor conserva el comportamiento nativo de <textarea>, su servidor maneja los datos como una cadena estándar. No se requiere lógica adicional: no hay preventDefault() ni construcción manual de FormData.

💡 Por qué esta es una "función excelente":

La mayoría de los editores (como Quill, Editor.js, simpleMDE, easyMDE) guardan datos en estructuras JSON complejas. Si un desarrollador los usa, debe reescribir el esquema de su base de datos y su lógica de representación.

Con MarkdownEditor, un desarrollador puede tomar un sitio web antiguo, reemplazar un <textarea> simple con su editor, y el backend ni siquiera sabe que cambió. Simplemente recibe el mismo texto sin formato de siempre, pero el usuario obtiene una experiencia 10 veces mejor.

Marco / Idioma Cómo acceder al contenido de Markdown
PHP $_POST['content']
Django request.POST.get('content')
Node.js (Express) req.body.content
Laravel $request->input('content')
Ruby on Rails params[:content]

Opciones de configuración

🖼️ Carga de imágenes avanzada

Manejar la carga de imágenes de forma nativa, en lugar de depender de cadenas Base64 lentas y con mucha memoria, es una ganancia significativa tanto para el rendimiento como para el SEO.

Opciones de configuración

La herramienta de imágenes admite una configuración fileInput para manejar cargas directas al servidor.

  • aceptar: define una serie de formatos de imagen permitidos (por ejemplo, 'webp', 'avif')
  • uploadUrl: especifique el punto final del servidor donde se enviará el objeto File a través de POST.
  • params: objeto opcional para enviar datos adicionales (como tokens CSRF, ID de usuario o nombres de carpetas) junto con el archivo de imagen.

Ejemplo de uso (configuración completa)

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);

📡 Detalles de integración del servidor

1. La Solicitud

El editor envía una solicitud POST como multipart/form-data. Por defecto, incluye:

  • image_file: El objeto de archivo real
  • image_alt: el texto alternativo ingresado por el usuario
  • ...más cualquier dato personalizado definido en el objeto params
2. La respuesta requerida

Para confirmar una carga exitosa e insertar la imagen en el editor, su servidor debe devolver la siguiente estructura JSON:

json
1
2
3
4
{
  "success": true,
  "image_path": "https://cdn.yourdomain.com/uploads/image.webp"
}

Nota: asegúrese de utilizar la clave image_path para la URL de la imagen cargada.

Validación de texto alternativo de imagen (altInput)

Para garantizar que su contenido siga siendo accesible y compatible con SEO, MarkdownEditor aplica la validación de texto alternativo de forma predeterminada. Puede configurar este comportamiento utilizando una taquigrafía booleana o un objeto detallado.

  • Comportamiento predeterminado: si altInput no está definido, el valor predeterminado es { require: true }
  • Hacer cumplir la accesibilidad: se impedirá que los usuarios inserten una imagen hasta que se proporcione una descripción alternativa.
Ejemplos de configuración:
1. Predeterminado (No se necesita configuración)
javascript
1
2
3
4
// Alt text is REQUIRED by default
image: {
  fileInput: { uploadUrl: '/api/upload' }
}
2. Taquigrafía (desactivar validación)

Si desea permitir imágenes sin descripciones, simplemente establezca el valor booleano en false.

javascript
1
2
3
image: {
  altInput: false // Users can now skip the alt text field
}
3. Basado en objetos (explícito)
javascript
1
2
3
4
5
image: {
    altInput: {
        required: false // Disables alt text validation — users can skip the alt field
    }
}

Uso de imagen estándar (sin fileInput):

Si fileInput no está configurado, el editor utiliza de forma predeterminada un modal simple basado en URL. Esto es ideal si sus usuarios se vinculan principalmente a servidores de imágenes externos.

javascript
1
2
3
4
5
6
7
8
const options = {
  toolbar: [
    'link',
    'image',
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);
💡 ¿Por qué utilizar parámetros?

En frameworks como Laravel o Django, no puedes cargar archivos sin un token CSRF. Al agregar _token al objeto params, su solicitud pasará a través del middleware de seguridad del backend sin problemas, manteniendo la filosofía de "Lógica Cero" para sus controladores del lado del servidor.

🔀 Modos de edición

MarkdownEditor ofrece dos formas distintas de escribir y formatear su contenido. Puede alternar entre una vista tradicional centrada en la sintaxis o una experiencia moderna y visual.

Configuración

Puede definir el modo de inicio utilizando la propiedad mode durante la inicialización.

  • plain (Predeterminado): un entorno Markdown limpio y de alto rendimiento donde la sintaxis (como **bold** o # encabezado) es visible. Ideal para desarrolladores y puristas de Markdown
  • híbrido: una experiencia inspirada en WYSIWYG que representa el formato (negrita, cursiva, encabezados) en tiempo real a medida que escribe, manteniendo la estructura subyacente de Markdown.
Implementación:
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 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'
});
Vista previa del modo híbrido y normal:
Modo híbrido

El formato visual se representa en tiempo real mientras escribe.

Modo simple (predeterminado)

Se centra en la sintaxis original de Markdown para una experiencia ligera.

configuración Propiedad / Herramienta Descripción
Objeto de opciones placeholder Establece el texto del marcador de posición para el área de texto (opcional, ya que también puede usar el atributo de área de texto HTML estándar)
mode: 'hybrid' Permite una experiencia inspirada en WYSIWYG que muestra el formato (negrita, cursiva, encabezados) en tiempo real a medida que escribe.
barra de herramientas: determina qué herramientas
aparecen en la barra de herramientas y su orden.
heading Abre un menú desplegable para seleccionar el nivel de título H1–H6
bold Habilita el formato de texto en negrita.
italic Habilita el formato de texto en cursiva.
strikethrough Permite tachar texto.
ol (Lista ordenada): convierte texto a un formato de lista numerada.
ul (Lista desordenada): convierte el texto en una lista con viñetas.
checklist Agrega casillas de verificación a su texto, lo que lo hace ideal para tareas, listas de tareas pendientes o seguimiento del estado de finalización.
blockquote Resalte el texto citado o enfatizado.
code Envuelve el texto seleccionado con comillas invertidas individuales para el código en línea. Al hacer clic nuevamente se eliminan las comillas invertidas.
codeblock Envuelve el texto seleccionado en un bloque de código delimitado con triple acento grave. Al hacer clic nuevamente se eliminan las vallas.
hr Inserta una regla horizontal --- en la posición del cursor en su propia línea.
table Inserta una plantilla de tabla de rebajas inicial de 2x3 en la posición del cursor.
image Le permite insertar imágenes mediante la sintaxis de rebajas.
link Le permite agregar hipervínculos a su texto.
undo Para revertir los últimos cambios.
redo Para volver a aplicar los últimos cambios deshechos.
indent Para aumentar el nivel de sangría.
outdent Para disminuir el nivel de sangría.
preview Alterna una vista previa en pantalla completa, una al lado de la otra. Se puede hacer clic en las casillas de verificación en el panel de vista previa y se actualiza la fuente de rebajas al instante. Presione Escape para salir de la pantalla completa.
Función avanzada de carga de imágenes:
Permite configurar la carga de imágenes en
su propio servidor y configurar la ruta
de la imagen a través de una API. Esto mejora el rendimiento y el SEO.
fileInput accept: conjunto de tipos de archivos de imagen permitidos (por ejemplo, 'webp', 'avif').
uploadUrl: punto final del backend donde se envía el archivo a través de POST.
params: objeto opcional para datos adicionales (tokens CSRF, ID de usuario, nombres de carpetas)
altInput obligatorio: false: deshabilita la validación de entrada de texto alternativo (el valor predeterminado es verdadero)

⌨️ Atajos de teclado

Las acciones de formato comunes se pueden activar directamente desde el teclado sin tocar la barra de herramientas. Cada acceso directo también se muestra en la información sobre herramientas del botón de la barra de herramientas correspondiente.

Atajo Acción
Ctrl + B  /  ⌘ B Alternar negrita
Ctrl + I  /  ⌘ I Alternar Cursiva
Ctrl + K  /  ⌘ K Insertar enlace
Ctrl + `  /  ⌘ ` Alternar Código en línea
Ctrl + Shift + S  /  ⌘ ⇧ S Alternar Tachado
Ctrl + Z  /  ⌘ Z Deshacer
Ctrl + Shift + Z  /  ⌘ ⇧ Z Rehacer
Tab Sangrar líneas seleccionadas
Shift + Tab Eliminar sangría de líneas seleccionadas
Ctrl + F  /  ⌘ F Abrir panel de búsqueda
Ctrl + H  /  ⌘ H Abrir el panel Buscar y reemplazar
Escape Cerrar el panel Buscar/Salir de la vista previa en pantalla completa

🔍 Encuentra y busca Reemplazar

Un panel integrado de búsqueda y reemplazo está disponible dentro del editor; no se necesita extensión del navegador ni herramienta separada.

  • Presione Ctrl + F (o ⌘ F) para abrir el panel Buscar.
  • Presione Ctrl + H (o ⌘ H) para abrir la página Buscar y buscar. Reemplazar panel
  • La búsqueda no distingue entre mayúsculas y minúsculas y muestra un contador de partidos en vivo (por ejemplo, 3 de 12).
  • Navega por coincidencias con los botones ▲ / ▼ o Intro / Shift + Enter
  • Reemplazar reemplaza la coincidencia resaltada actual; Reemplazar todo reemplaza cada ocurrencia a la vez
  • Presione Escape para cerrar el panel y devolver el foco al editor.

El panel flota en la esquina superior derecha del área de contenido del editor y no interrumpe la escritura.

🌙 Tematización

MarkdownEditor hereda automáticamente su tema de la página circundante, sin necesidad de configuración. El editor lee data-theme del ancestro más cercano en la inicialización, por lo que permanece sincronizado con el tema de su sitio desde el primer momento.

Cómo se resuelve el tema (orden de prioridad)

  1. Opción tema: anulación explícita pasada en el objeto de opciones
  2. data-theme en <textarea>: se establece directamente en el elemento
  3. tema de datos en cualquier antepasado, p. <html>, <body> o un contenedor <div>

Temas disponibles

'light' (predeterminado), 'dark', 'snowberry', 'darkberry'

Opción 1: heredar de <html> o de cualquier antepasado (configuración cero)
html
1
2
3
4
5
6
<html data-theme="dark">
  ...
  <textarea id="markdown-editor"></textarea>
  <script>
    new MarkdownEditor('#markdown-editor'); // picks up dark automatically
  </script>
Opción 2: configurar data-theme directamente en <textarea>
html
1
2
3
4
<textarea id="markdown-editor" data-theme="dark"></textarea>
<script>
  new MarkdownEditor('#markdown-editor');
</script>
Opción 3: opción theme explícita (anula todo)
javascript
1
2
3
new MarkdownEditor('#markdown-editor', {
    theme: 'dark'
});

🎨 Tema personalizado a través de variables CSS

Puede personalizar completamente la apariencia del editor anulando sus variables CSS en el elemento .markdown-editor-wrapper o cualquier selector [data-theme]. Todos los colores utilizan el espacio de color OKLCH para obtener resultados perceptualmente uniformes.

Variable Objetivo Luz predeterminada Valor predeterminado oscuro
--color-base Fondo del editor oklch(100% 0 0) oklch(10.9% 0 0)
--color-on-base Color de texto principal oklch(22% 0 0) oklch(98% 0 0)
--color-primary Acento principal (barra de herramientas activa, enlaces) oklch(51.1% .262 277) oklch(66.4% .184 286)
--color-on-primary Texto en superficies de colores primarios oklch(96.2% .018 272) oklch(10% .01 270)
--color-secondary Acento secundario oklch(59.1% .293 323) oklch(65% .18 220)
--color-accent Resaltar acento (código en línea, cursiva) oklch(54.1% .281 293) oklch(75% .18 50)
--color-neutral Superficies neutras (bordes, divisores) oklch(15% 0 0) oklch(85% 0 0)
--color-error Color del estado de error oklch(57.7% .245 27) oklch(60% .22 30)
--border-radius Redondeo de esquinas del marco del editor 0.25rem
Ejemplo de tema personalizado

Anule cualquier variable en .markdown-editor-wrapper después de que se inicialice el editor, o defina un bloque [data-theme] personalizado en su hoja de estilo:

css
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/* 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' });
  • Vista previa en tiempo real: vea su descuento renderizado instantáneamente a medida que escribe.
  • Resaltado de sintaxis: Legibilidad mejorada con código claro y formato de rebajas.
  • Fácil integración: integre perfectamente en cualquier proyecto web con una configuración mínima.
  • Barra de herramientas personalizable: configure y reordene dinámicamente las opciones de la barra de herramientas como negrita, cursiva y más.

Características

🔌 Integración de formularios nativos

Funciona exactamente como un <textarea> estándar. Sin API complejas: solo use el atributo value o name. "Simplemente funciona" con envíos de formularios HTML estándar en PHP, Django o Node.js.

🖼️ Carga de imágenes avanzada

Configure las cargas del servidor nativo a través de API. Evite cadenas Base64 pesadas para garantizar cargas de página más rápidas y un SEO superior al alojar imágenes en su propia CDN.

🔀 Modos híbridos y simples

Cambie entre una experiencia híbrida (WYSIWYG) para edición visual o el modo Plain Markdown para una sensación de codificación tradicional.

🚀 Alto rendimiento

Un pequeño paquete de ~116 KB optimizado para "contenido pesado". Maneja documentos y archivos de gran tamaño sin ningún retraso en la entrada ni caída del rendimiento.

🌍 Soporte RTL incorporado

Soporte nativo para idiomas de derecha a izquierda como árabe, urdu y farsi. Perfecto para crear aplicaciones accesibles globalmente.

🌙 Temas adaptativos

Incluye soporte automático para el modo oscuro. Se sincroniza con la configuración del sistema o con la biblioteca Frutjam UI para una experiencia visual perfecta.

📝 Edición inteligente

Continuación de lista automática al estilo GitHub para listas ordenadas, listas desordenadas y listas de verificación: presione Enter y el editor continuará el patrón. Se puede hacer clic en las casillas de verificación en el panel de vista previa y se sincronizan con la fuente de rebajas al instante.

📱 Totalmente receptivo

Una interfaz de usuario fluida y pensada para dispositivos móviles que se adapta perfectamente a computadoras de escritorio, tabletas y teléfonos inteligentes para editar sobre la marcha.

📦 Soporte universal

Compatible con ESM, UMD, CommonJS y IIFE. Funciona de inmediato a través de CDN (<script src>), npm o cualquier paquete (Vite, webpack, Rollup); no se necesita configuración adicional.

♿ Accesible por defecto

Compatibilidad total con ARIA incorporada: punto de referencia de la barra de herramientas, región de vista previa etiquetada, botones fáciles de leer en pantalla, aria-pressed en el interruptor de vista previa, disabled y aria-disabled en herramientas inactivas y restauración correcta del enfoque cuando se cierran los modales.

🛡️ Cero conflictos de CSS

Los estilos del editor tienen un alcance completo en .markdown-editor-wrapper. La verificación previa global de Tailwind está excluida, por lo que el editor convive de forma segura junto con Bootstrap, Tailwind o cualquier otro marco sin alterar sus estilos.

⌨️ Atajos de teclado

Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S: acciones de formato comunes sin tocar el mouse. Cada acceso directo se muestra en la información sobre herramientas del botón de la barra de herramientas.

🔍 Encuentra y busca Reemplazar

Presione Ctrl+F para buscar o Ctrl+H para abrir Buscar & reemplazar. Búsqueda que no distingue entre mayúsculas y minúsculas con contador de partidos en vivo, navegación siguiente/anterior, reemplazo único y reemplazo todo, sin salir del editor.

Ejemplo de configuración completa

Utilice este ejemplo completo para inicializar MarkdownEditor con todas las funciones principales, incluido el orden personalizado de la barra de herramientas y el manejo avanzado de carga de imágenes.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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();