Desarrollo un editor HTML con React.js (WYSIWYG)

Estas últimas semanas he estado explorando los diferentes editores Markdown para un side-project. Todo empezó como un text-area
en el que copiaba manualmente el markdown que editaba en algún otro editor (obsidian, notion, dillinger). Luego probé a añadir una previsualización tipo WYSIWYG (del inglés "What You See Is What You Get"), acabé explorando diferentes opciones para no reinventar la rueda: ProseMirror/CodeMirror que usa TipTap, Ace (aunque parece olvidado), Draft.js (obsoleto), Lexical.
Investigando veo cómo Obsidian utiliza CodeMirror internamente, dillinger.io utiliza Ace (que no se ha actualizado su repo en 7 años, de hecho usa node 16). También está lexical de Meta, el cual me parece super potente pero no tiene prácticamente documentación y desarrollar supone muchos quebradores de cabeza. Tras leer mucho, la mejor opción es utilizar TipTap, que se nota que es una empresa que lo tiene cuidado. El editor es open source y funciona sobre CodeMirror / ProseMirror, que tienen algo más documentación.
Tras varios días leyendo y desarrollando al final me pareció interesante estudiar cómo funcionan estos editores internamente y he visto que hay dos opciones principalmente:
Utilizar un
textarea
"oculto" que hace de proxy hacia un div. El textarea se encarga del I/O pero tiene la limitación que no permite añadir estilos ni colores, por lo que se usa un div para mostrar el contenido.Utilizar un
div
con el atributocontenteditable=true
. Esto permite que el propio navegador capture todos los eventos necesarios, y nosotros los interceptamos y gestionamos el estado del componente: cada vez que se presiona cualquier tecla, calculamos por un lado las modificaciones del texto, luego lo renderizamos, y finalmente los transpilamos a HTML y lo inyectamos al div para que lo renderice.
Suena fácil pero te aseguro que no lo es. Hay mucha complejidad en los diferentes puntos aunque es muy interesante cuanto menos, así que, ¿por qué no probarlo? La curiosidad siempre me lleva a probar a desarrollar este tipo de cosas.
En la carrera me encantó la asignatura de compiladores, donde hicimos nuestro propia sintaxis que compilaba a C++, y desde entonces el tema de los automátas, lexer, parser... me encanta. Además es un tema muy relevante en el mundo del front con toda la iniciativa en Rust por un lado de SWC/Turbopack, y por otro lado la de void0 que está detrás de RollDown y Vite 6, o RsPack de TikTok. En fin, que nos desviamos del tema inicial.
Estos últimos días he estado trabajando en una prueba de concepto. Es mucho más complejo de lo que parece y tiene muchísimo trabajo: ¿qué estructura de datos utilizar? ¿cómo gestionar los eventos del HTML? ¿Es mejor tener un estado interno y luego renderizarlo o no?
Me parece interesante subir el código del editor a un repositorio de GitHub por si alguien más quiere experimentar. El estado actual es un PoC ya que hay teclas que no están implementadas y por otro lado hay casos esquina que gestionar correctamente. No tengo pensado continuarlo por ahora.
¿Te ha parecido interesante el artículo?¡ Únete a la comunidad para recibir contenido exclusivo !