Un editor basado en React y Prosemirror que impulsa Outline y también se puede usar para mostrar contenido en modo de solo lectura. El editor es WYSIWYG e incluye herramientas de formato, al tiempo que conserva la capacidad de escribir atajos de Markdown en línea y generar Markdown sin formato. Vea el libro de cuentos de demostración en vivo .
Nota importante: este proyecto no pretende ser un editor de Markdown multiuso . Está diseñado para la base de conocimientos de Outline y, aunque otros pueden bifurcar o utilizar este paquete en sus propios productos, las decisiones de desarrollo se centran en las necesidades de Outline.
yarn add rich-markdown-editor
o
npm install rich-markdown-editor
Tenga en cuenta que los componentes react
, react-dom
y styled-components
son dependencias entre pares requeridas .
import Editor from "rich-markdown-editor" ;
< Editor
defaultValue = "Hello world!"
/>
Clona este repositorio y ejecuta Storybook con yarn start
para ver una amplia variedad de ejemplos de uso.
id
Una identificación única para este editor, utilizada para conservar la configuración en el almacenamiento local. Si no se pasa ninguna id
, el editor utilizará de forma predeterminada el nombre de la ruta de ubicación.
defaultValue
Una cadena de rebajas que representa el valor inicial del editor. Utilice esto para restaurar el contenido previamente guardado para que el usuario continúe editando.
value
Una cadena de rebajas que representa el valor del editor. Utilice este accesorio para cambiar el valor del editor una vez montado; esto volverá a representar todo el editor y, como tal, solo es adecuado cuando también está en modo readOnly
. No canalice el valor de onChange
nuevamente a value
, el editor mantiene su propio estado interno y esto resultará en efectos secundarios inesperados.
placeholder
Permite anular el marcador de posición. El valor predeterminado es "Escribe algo bonito...".
readOnly
Con readOnly
establecido en false
el editor está optimizado para la composición. Cuando true
el editor se puede utilizar para mostrar contenido escrito previamente: los títulos ganan anclajes y se puede hacer clic en los enlaces.
readOnlyWriteCheckboxes
Con readOnlyWriteCheckboxes
configurado en true
las casillas de verificación aún se pueden marcar o desmarcar como un caso especial, mientras que readOnly
está configurado en true
y, de lo contrario, el editor no se puede editar.
autoFocus
Cuando se establece true
junto con readOnly
establecido en false
, se enfoca automáticamente al final del documento.
maxLength
Cuando se establece, se aplica una longitud máxima de caracteres en el documento, sin incluir la sintaxis de rebajas.
extensions
Permite pasar complementos de Prosemirror adicionales a la instancia de Prosemirror subyacente.
disableExtensions
Lista de nombres de extensiones incluidas para deshabilitar. Elimina los elementos de menú y comandos correspondientes. Por ejemplo, establezca en ["em", "blockquote"]
para desactivar el texto en cursiva y las comillas en bloque.
theme
Permite anular el tema incorporado para personalizar el editor; por ejemplo, use su propia fuente y colores de marca para que el editor se ajuste a su aplicación. Consulte el tema incorporado para ver un ejemplo de las claves que se deben proporcionar.
dictionary
Permite anular el diccionario de copia incorporado, por ejemplo, para internacionalizar el editor. Consulte el diccionario incorporado para ver un ejemplo de las claves que se deben proporcionar.
dark
Con dark
configurado en true
el editor usará un tema oscuro predeterminado que está incluido. Vea la fuente aquí.
dir
Predeterminado: auto
Controla la dirección del documento. Los valores posibles son:
ltr
: el diseño del editor está optimizado para documentos LTR y el contenido está marcado explícitamente como LTR.rtl
: el diseño del editor está optimizado para documentos RTL y el contenido está marcado explícitamente como RTL.auto
: el navegador decide el diseño del editor en función del contenido del documento. tooltip
Un componente de React que se incluirá alrededor de elementos que tienen una información sobre herramientas opcional. Puede usar esto para inyectar su propia biblioteca de información sobre herramientas en el editor; al componente se le pasarán los siguientes accesorios:
tooltip
: un nodo React con el contenido de información sobre herramientasplacement
: Enum top
, bottom
, left
, right
children
: el componente que envuelve la información sobre herramientas debe representarse headingsOffset
Un número que compensará los encabezados del documento en varios niveles. Por ejemplo, si ya anida el editor bajo un título h1
principal, es posible que desee que el usuario solo pueda crear encabezados h2
e inferiores; en este caso, establecería el accesorio en 1
.
scrollTo
Una cadena que representa un ancla de encabezado: el documento se desplazará suavemente para que el encabezado sea visible en la ventana gráfica.
embeds
Opcionalmente, defina incrustaciones que se insertarán en lugar de enlaces cuando la función matcher
devuelva un valor verdadero. El valor de retorno del método de comparación estará disponible en el componente en props.attrs.matches
. Si se proporcionan title
y icon
, la inserción también aparecerá en el menú de bloqueo.
< Editor
embeds = { [
{
title : "Google Doc" ,
keywords : "google docs gdocs" ,
icon : < GoogleDocIcon /> ,
defaultHidden : false ,
matcher : href => href . matches ( / docs.google.com / i ) ,
component : GoogleDocEmbed
}
] }
/>
uploadImage(file: Blob): Promise<string>
Si desea que el editor admita imágenes, debe proporcionar esta devolución de llamada. La devolución de llamada debe aceptar un único objeto File
y devolver una promesa que se resuelve en una URL cuando la imagen se ha cargado en una ubicación de almacenamiento, por ejemplo, S3. p.ej:
< Editor
uploadImage = { async file => {
const result = await s3 . upload ( file ) ;
return result . url ;
} }
/>
onBlur(): void
Esta devolución de llamada se activa cuando el usuario pierde el foco en el editor contenteditable y en todos los elementos de la interfaz de usuario asociados, como el menú de bloqueo y las barras de herramientas flotantes. Si desea escuchar eventos de desenfoque solo en el área de contenido, utilice los accesorios handleDOMEvents
.
onFocus(): void
Esta devolución de llamada se activa cuando el usuario se concentra en el editor contenteditable o en cualquier elemento de la interfaz de usuario asociado, como el menú de bloqueo o las barras de herramientas flotantes. Si desea escuchar eventos de enfoque solo en el área de contenido, utilice los accesorios handleDOMEvents
.
onSave({ done: boolean }): void
Esta devolución de llamada se activa cuando el usuario solicita explícitamente guardar usando un método abreviado de teclado, Cmd+S
o Cmd+Enter
. Puede utilizar esto como señal para guardar el documento en un servidor remoto.
onCancel(): void
Esta devolución de llamada se activa cuando se presiona Cmd+Escape
dentro del editor. Puede usarlo para cancelar la edición.
onChange(() => value): void
Esta devolución de llamada se activa cuando cambia el contenido del editor, generalmente debido a la entrada del usuario, como la pulsación de una tecla o el uso de opciones de formato. Puede usar esto para conservar localmente el estado de los editores.
Devuelve una función que, cuando se llama, devuelve el valor de texto actual del documento. Esta optimización se realiza para evitar serializar el estado del documento en texto en cada evento de cambio, lo que permite que la aplicación host elija cuándo necesita el valor serializado.
onImageUploadStart(): void
Esta devolución de llamada se activa antes de uploadImage
y se puede usar para mostrar alguna interfaz de usuario que indique que hay una carga en progreso.
onImageUploadStop(): void
Se activa una vez que la carga de una imagen se realizó correctamente o falló.
onSearchLink(term: string): Promise<{ title: string, subtitle?: string, url: string }[]>
El editor ofrece la posibilidad de buscar enlaces para insertar desde la barra de herramientas de formato. Si se proporciona esta devolución de llamada, debería aceptar un término de búsqueda como único parámetro y devolver una promesa que se resuelva en una matriz de objetos. p.ej:
< Editor
onSearchLink = { async searchTerm => {
const results = await MyAPI . search ( searchTerm ) ;
return results . map ( result => {
title : result . name ,
subtitle : `Created ${ result . createdAt } ` ,
url : result . url
} )
} }
/>
onCreateLink(title: string): Promise<string>
El editor ofrece la posibilidad de crear enlaces desde la barra de herramientas de formato para la creación de documentos sobre la marcha. Si se proporciona esta devolución de llamada, debe aceptar un "título" del enlace como único parámetro y devolver una promesa que se resuelva en una URL para el enlace creado, por ejemplo:
< Editor
onCreateLink = { async title => {
const url = await MyAPI . create ( {
title
} ) ;
return url ;
} }
/>
onShowToast(message: string, type: ToastType): void
Se activa cuando el editor desea mostrar un mensaje al usuario. Conéctese al sistema de notificación de su aplicación o use de manera simplista window.alert(message)
. El segundo parámetro es el tipo de brindis: 'error' o 'información'.
onClickLink(href: string, event: MouseEvent): void
Esta devolución de llamada permite anular el manejo de enlaces. A menudo se da el caso de que desee que los enlaces externos abran una nueva ventana y que los enlaces internos utilicen algo como react-router
para navegar. Si no se proporciona ninguna devolución de llamada, el comportamiento predeterminado de abrir una nueva pestaña se aplicará a todos los enlaces. p.ej:
import { history } from "react-router" ;
< Editor
onClickLink = { ( href , event ) => {
if ( isInternalLink ( href ) ) {
history . push ( href ) ;
} else {
window . location . href = href ;
}
} }
/>
onHoverLink(event: MouseEvent): boolean
Esta devolución de llamada permite detectar cuando el usuario pasa el cursor sobre un enlace del documento.
< Editor
onHoverLink = { event => {
console . log ( `Hovered link ${ event . target . href } ` ) ;
} }
/>
onClickHashtag(tag: string, event: MouseEvent): void
Esta devolución de llamada permite el manejo de hacer clic en hashtags en el texto del documento. Si no se proporciona ninguna devolución de llamada, los hashtags se mostrarán como texto normal, por lo que puedes elegir si los admites o no pasando este accesorio.
import { history } from "react-router" ;
< Editor
onClickHashtag = { tag => {
history . push ( `/hashtags/ ${ tag } ` ) ;
} }
/>
handleDOMEvents: {[name: string]: (view: EditorView, event: Event) => boolean;}
Este objeto asigna nombres de eventos ( focus
, paste
, touchstart
, etc.) a funciones de devolución de llamada.
< Editor
handleDOMEvents = { {
focus : ( ) => console . log ( "FOCUS" ) ,
blur : ( ) => console . log ( "BLUR" ) ,
paste : ( ) => console . log ( "PASTE" ) ,
touchstart : ( ) => console . log ( "TOUCH START" ) ,
} }
/>
El componente Editor expone algunos métodos para interactuar con el editor montado.
focusAtStart(): void
Coloque el cursor al inicio del documento y enfóquelo.
focusAtEnd(): void
Coloque el cursor al final del documento y enfóquelo.
getHeadings(): { title: string, level: number, id: string }[]
Devuelve una matriz de objetos con el contenido de texto de todos los encabezados del documento, su nivel en la jerarquía y la identificación del ancla. Esto es útil para construir su propia tabla de contenido ya que la opción toc
se eliminó en v10.
Este proyecto utiliza hilo para gestionar las dependencias. Puede usar npm, sin embargo, no respetará el archivo de bloqueo de hilo y puede instalar versiones ligeramente diferentes.
yarn install
Cuando se ejecuta en desarrollo, Storybook se incluye en editores de ejemplo con recarga en caliente. Después de instalar las dependencias, ejecute yarn start
a funcionar.
Al desarrollar usando yarn link
, puede usar yarn watch
para reconstruir continuamente los cambios en dist
a medida que realiza cambios.
Este proyecto tiene licencia BSD.