WYSIWYG y editor de marcado basado en Gravity UI/Habr

TL;DR

¡Hola Habr! Mi nombre es Sergey Makhnatkin, trabajo como desarrollador en el departamento de Experiencia de usuario de Yandex Cloud. El año pasado escribimos sobre nuestro sistema de diseño y biblioteca de componentes de Gravity UI. Desde entonces, el sistema se ha actualizado más de una vez y ha adquirido nuevas funciones, y hoy quiero hablarles de una nueva herramienta: Markdown Editor, que simplifica enormemente el proceso de trabajo con documentación.

Hablemos de la historia de la creación de la interfaz de usuario, las características arquitectónicas y los detalles técnicos de la integración y desarrollo de nuestras propias extensiones, y luego de por qué todo esto está disponible en código abierto.

Por cierto, puedes probar la herramienta aquí:

¿Por qué necesitamos nuestro propio editor Markdown?

Para facilitar el almacenamiento y estructuración de la información corporativa, hemos desarrollado una plataforma wikique permite crear bases de conocimiento. Además de la base de conocimientos, desarrollamos enfoques para la documentación, como Docs as Code, donde la documentación y el código conviven en el almacenamiento de archivos (archivos .md). Así apareció la plataforma diplodoс.

Wiki y Diplodoc están unidos por el hecho de que ambas plataformas funcionan con el dialecto de rebajas: Yandex Flavored Markdown (YFM), que se utiliza en Nebius, Bitrix, DoubleCloud, Mappable, Meteum.

Con el tiempo, notamos que hay dos grupos de usuarios que tienen ideas diferentes sobre el proceso de creación y edición de texto. Algunas personas prefieren ver inmediatamente el resultado final cuando trabajan con texto, como en MS Word, Confluence o Notion. Otros confían únicamente en el marcado y prefieren diseñar páginas utilizando el marcado. No encontramos ninguna biblioteca conocida que funcione simultáneamente en modo WYSIWYG/markdown. Por ejemplo, Notion es solo WYSIWYG y los editores de código solo tienen modo de rebajas y vista previa.

Hemos desarrollado un editor de rebajas que puede funcionar simultáneamente en dos modos: visual (WYSIWYG) y modo de rebajas. En el primer modo, los íconos en el panel ayudan a marcar el texto y en el segundo modo, los usuarios pueden editar manualmente el código de rebajas. Además, nuestra solución guarda el documento como un archivo md, independientemente del modo que se utilizó al crearlo.

Así es como se ve el editor visual, en el que se puede formatear el texto usando botones:

Y este es un modo de marcado en el que los elementos de formato se indican mediante caracteres especiales:

Funciones de Markdown Editor en Gravity UI

El editor cumple con el estándar CommonMark, admite el lenguaje de rebajas estándar y el lenguaje YFM. También agregamos la capacidad de ampliar la sintaxis con otros dialectos de rebajas, como Github Flavored Markdown. En este caso, el editor le permite cambiar del modo de marcado al modo WYSIWYG, y el documento en sí se almacenará como marcado md o md extendido (por ejemplo, en el caso de YFM).

Extensiones

El editor viene prediseñado con muchas extensiones y configuraciones. Por ejemplo, gráficos Sirena y bloques HTML:

Intentamos hacer que el núcleo del editor fuera fácilmente extensible. Los desarrolladores pueden crear su propia extensión o funcionalidad adicional que ayudará a:

  • agregar nuevas entidades: bloques o modificadores de texto;

  • configure adicionalmente el analizador de rebajas;

  • agregue acciones que le permitan trabajar con el editor desde fuera;

  • enriquecer la funcionalidad de la interfaz, por ejemplo, mostrar un menú de comandos disponibles al ingresar una barra diagonal;

  • modificar el comportamiento actual, como insertar imágenes y archivos y cargarlos en el almacenamiento.

Aquí hay una serie de ejemplos de extensiones que hemos desarrollado para nuestro Wiki:

El marcado se puede convertir automáticamente. Si prefiere trabajar sin mouse, el modo de editor visual proporciona símbolos especiales que le permiten aplicar marcas directamente a su texto. Por ejemplo, ** convertir texto a negrita en modo WYSIWYG. Con estos símbolos, puede formatear texto y crear código en línea y de bloque.

También puede acceder al menú de extensión ingresando el símbolo /.

Preajustes

El editor le permite configurar la barra de herramientas para cada proyecto por separado, pero viene con una serie de configuraciones listas para usar: ajustes preestablecidos.

Editor sin ajustes preestablecidos:

Preajuste de marca común proporciona soporte para elementos de rebajas estándar: negrita, cursiva, encabezados, listas, enlaces, citas, bloques de código.

EN preestablecido por defecto También aparece texto tachado, así como una tabla cuyas celdas sólo pueden contener texto. Este ajuste preestablecido corresponde al Markdown-it estándar.

Como se mencionó anteriormente, el editor también es compatible con YFM, por lo que se integra perfectamente con Diplodoc. EN presione YFM Aparecen elementos adicionales: tablas mejoradas, inserción de archivos e imágenes, casillas de verificación, corte, pestañas, fuente monoespaciada.

Preajuste completo contiene aún más elementos.

Arquitectura

El editor en modo WYSIWYG se basa en una biblioteca conocida ProsaEspejoy se utiliza para marcar Código espejo. ProseMirror admite la edición formateada, mientras que CodeMirror es adecuado para situaciones en las que necesita trabajar con texto sin marcar.

Elegimos estas bibliotecas porque fueron desarrolladas por un autor, tienen la misma arquitectura y enfoques de implementación, cuentan con el respaldo de una gran comunidad, se utilizan en muchos editores y están bien optimizadas para trabajar con texto. Por ejemplo, un sistema de transacciones para realizar cambios en un documento, decoraciones para una vista, virtualización DOM o soporte para la sintaxis de muchos lenguajes de programación.

Integración

Nuestro editor se puede conectar fácilmente como gancho reaccionar:

import React from 'react';
import {useMarkdownEditor, MarkdownEditorView} from '@gravity-ui/markdown-editor';
import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18';

function Editor({onSubmit}) {
  const editor = useMarkdownEditor({allowHTML: false});

  React.useEffect(() => {
    function submitHandler() {
      // Serialize current content to markdown markup
      const value = editor.getValue();
      onSubmit(value);
    }

    editor.on('submit', submitHandler);
    return () => {
      editor.off('submit', submitHandler);
    };
  }, (onSubmit));

  return <MarkdownEditorView stickyToolbar autofocus toaster={toaster} editor={editor} />;
}

Usamos componentes de la biblioteca uikit GravityUI. Esto garantiza que toda la interfaz sea coherente y siga las mismas guías de estilo. El uso de estos componentes también proporciona un alto grado de coherencia y reconocimiento para los usuarios, lo que hace que trabajar con el editor sea aún mejor.

Hemos detallado instruccionescómo conectar un editor a una aplicación React, así como cómo conectar varios tipos de extensiones: por ejemplo, YandexGPT, Sirena o Látex.

Integración de extensiones personalizadas.

Varias extensiones adicionales ya están integradas en el editor. Pero si esto no es suficiente, los desarrolladores pueden agregar sus extensiones al modo de edición WYSIWYG. Hablamos anteriormente sobre lo que pueden proporcionar las extensiones.

Si desea agregar un nuevo bloque o modificador de texto, primero debe configurar una instancia interna de Markdown-it usando el método configureMd. Entonces deberías agregar conocimiento sobre la nueva entidad usando métodos. addNode o addMarkpasando el nombre de la entidad y una función de devolución de llamada que devuelve un objeto con tres campos obligatorios:

import insPlugin from 'markdown-it-ins';
export const underlineMarkName="ins";

export const UnderlineSpecs: ExtensionAuto = (builder) => {
    builder
        .configureMd((md) => md.use(insPlugin))
        .addMark(underlineMarkName, () => ({
            spec: {
                parseDOM: ({tag: 'ins'}, {tag: 'u'}),
                toDOM() {
                    return ('ins');
                },
            },
            toMd: {open: '++', close: '++', mixable: true, expelEnclosingWhitespace: true},
            fromMd: {tokenSpec: {name: underlineMarkName, type: 'mark'}},
        }));
};
  • spec — especificación para ProseMirror;

  • fromMd – configuración para analizar el marcado de rebajas en una vista dentro de ProseMirror;

  • toMd – configuración para serializar una entidad en un marcado de rebajas.

Por ejemplo, a continuación se muestra la configuración de extensión para texto subrayado. Se puede ampliar agregando acción usando el método addAction:

import {toggleMark} from 'prosemirror-commands';

const undAction = 'underline';

builder
    .addAction(undAction, ({schema}) => ({
        isActive: (state) => Boolean(isMarkActive(state, markType)),
        isEnable: toggleMark(underlineType(schema)),
        run: toggleMark(underlineType(schema)),
      })
   )

Esta acción se puede llamar en un código como este:

// editor – инстанс редактора, полученный в результате вызова useMarkdownEditor
editor.actions.underline.run(),

en la documentacion Puede ver instrucciones completas para crear una nueva extensión.


Estamos constantemente ampliando los horizontes del uso de nuestro editor: actualmente estamos trabajando en un complemento para Código VSque le permitirá trabajar con archivos md en un cómodo modo WYSIWYG directamente desde el editor. También planeamos agregar un modo móvil completamente funcional. Esto permitirá a cada usuario trabajar en nuestro editor sólo con un teléfono móvil a mano.

Nuestro editor no apareció de la noche a la mañana: es el resultado de la acumulación de experiencia y conocimiento. Estamos orgullosos de que el editor se base completamente en productos de código abierto, incluidas las herramientas confiables y probadas ProseMirror, CodeMirror, Markdown-it, así como nuestros propios desarrollos: Diplodoc y Gravity UI.

Siempre puedes contribuir al desarrollo del editor: crear una solicitud de extracción o ayuda para resolver los problemas actuales enumerados en la sección Asuntos. Su apoyo y su nueva perspectiva nos ayudarán a mejorar el editor. Y si encuentra útil nuestro proyecto, ponga una estrella en nuestro repositorios en GitHubes valioso 🙂

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *