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.
Instalación
NPM (paquetes: Vite, webpack, Rollup, etc.)
npm install markdown-text-editor |
1 2 | import MarkdownEditor from 'markdown-text-editor'; new MarkdownEditor('#markdown-editor'); |
CDN: módulo ES
1 2 3 4 | <script type="module"> import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/+esm'; 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.
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> |
Demostración del editor de rebajas
Inicio rápido
Pase un objeto de opciones para personalizar el editor. Todas las opciones son opcionales: omita cualquiera para utilizar el valor predeterminado.
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'], }); |
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').valuecomo 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 | EasyMDE/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.
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'}), } |
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.
1 2 | <textarea name="content" class="markdown-editor">{{ old('content') }}</textarea> <script>new MarkdownEditor('.markdown-editor');</script> |
Ruby on Rails
Funciona con form_with listo para usar: params[:content] contiene la rebaja. Para Turbo Drive, utilice turbo:load en lugar de DOMContentLoaded.
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); }); }); |
Node.js/Expreso
req.body.content recibe la rebaja al enviar el formulario: sin paso de sincronización ni extracción personalizada.
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.
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> |
Configuració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 |
Referencia de herramientas
| Herramienta | Descripción |
|---|---|
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. |
💡 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
placeholderen JS, el complemento utilizará automáticamente el atributoplaceholderde 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
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 } }); |
🔀 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.
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 Markdownhí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.
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.
🌙 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)
- Opción
tema: anulación explícita pasada en el objeto de opciones data-themeen<textarea>: se establece directamente en el elementotema de datosen 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)
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>
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)
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:
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; } |
new MarkdownEditor('#markdown-editor', { theme: 'brand' }); |
API de 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.
Contenido de lectura y escritura
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.
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.
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 del contenido inicial del lado del servidor
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.
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.
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.
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.
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.
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); }); |
Envío de formulario
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.
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] |
🖼️ 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 objetoFilea través dePOST.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)
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); |
📡 Integración del servidor
La Solicitud
El editor envía una solicitud POST como multipart/form-data. Por defecto, incluye:
image_file: El objeto de archivo realimage_alt: el texto alternativo ingresado por el usuario- ...más cualquier dato personalizado definido en el objeto
params
La respuesta requerida
Para confirmar una carga exitosa e insertar la imagen en el editor, su servidor debe devolver la siguiente estructura 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.
- Comportamiento predeterminado: si
altInputno 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.
1. Predeterminado (No se necesita configuración)
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.
1 2 3 | image: { altInput: false // Users can now skip the alt text field } |
3. Basado en objetos (explícito)
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.
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.
⌨️ 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 |
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
Escapepara 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.
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 ~116KB optimizado para "contenido pesado". Maneja documentos y archivos de gran tamaño sin ningún retraso en la entrada ni caída del rendimiento. Actualizaciones de vista previa sin rebote, cálculos de estilo en caché y manejo del teclado sin conflictos, por lo que Tab y Enter siempre hacen exactamente una cosa.
🌍 Soporte RTL incorporado
Soporte nativo para idiomas de derecha a izquierda como árabe, urdu y farsi. Perfecto para crear aplicaciones accesibles globalmente.
✨ Resaltado de sintaxis
Legibilidad mejorada con código claro y formato de rebajas.
🌙 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.
🔒 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.
▶️ Vista previa en tiempo real
Vea su descuento renderizado instantáneamente a medida que escribe.
🔗 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.
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.
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 | 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; // destroy() when the view unmounts (SPAs) // editor.destroy(); |
¿Encontró esto útil?
Una estrella de GitHub ayuda a otros desarrolladores a descubrir el editor. Es parte de Frutjam. Una estrella allí también ayuda.
¿Usando Claude Code, Cursor u otro editor de IA?
Cherry MCP le brinda a su editor de IA la estructura y los nombres exactos de las clases Editor de rebajas según sea necesario. No más clases alucinadas.