React Component Wrapper para Easymde (la bifurcación simplemde más fresca).
Solo dos dependencias, React (Peer) y Easymde (Peer).
Construido por @rip21?
easymde , codemirror o cursor para poder manipularlo.Tabla de contenido generado con Markdown-Toc
>=16.8.2easymde ahora una dependencia de pares, instálelo manualmentelabeloptions [Breaking] se memorizarán para evitar que se creen nuevas instancias en cada renderizado y otros relacionados con esos errores (más sobre eso a continuación)ref ] ref div@babel/runtime Helpers ya no se incluyen sino que se importan. npm install --save react-simplemde-editor easymde
Nota: Posiblemente sea posible que deba instalar @babel/runtime , intente sin él, pero si no tiene ningún problema, entonces no debería hacerlo.
Demostración alojada
o para verlo localmente:
git clone https://github.com/RIP21/react-simplemde-editor.git
cd react-simplemde-editor
yarn install
yarn demo
open browser at localhost:3000
Ver el código de demostración para obtener más ejemplos.
Todos los ejemplos a continuación están en TypeScript
Uso no controlado
import React from "react" ;
import SimpleMDE from "react-simplemde-editor" ;
import "easymde/dist/easymde.min.css" ;
< SimpleMDE /> ; export const ControlledUsage = ( ) => {
const [ value , setValue ] = useState ( "Initial value" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
return < SimpleMdeReact value = { value } onChange = { onChange } /> ;
} ; Puede establecer API de opciones de simplemde que transmite como un accesorio options . Si está utilizando TypeScript, será inferido por el compilador.
Nota: Si no especifica una ID personalizada, generará automáticamente una ID para usted.
¡Tenga en cuenta que necesita useMemo para memorizar options para que no cambien en cada rerender! Afectará el comportamiento y el rendimiento porque luego en cada renderizado del padre que hace que SimpleMdeReact obtendrá una nueva instancia del editor, ¡lo que definitivamente desea evitar! Además, si cambia options en cada cambio value , perderá el enfoque. Por lo tanto, options de venta como un const afuera del componente, o si options se establecen parcial o completamente por props , asegúrese de useMemo en caso de componentes funcionales/de gancho, o campo de clase para componentes basados en class . Un poco más sobre eso aquí: #164
export const UsingOptions = ( ) => {
const [ value , setValue ] = useState ( "Initial" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
const autofocusNoSpellcheckerOptions = useMemo ( ( ) => {
return {
autofocus : true ,
spellChecker : false ,
} as SimpleMDE . Options ;
} , [ ] ) ;
return (
< SimpleMdeReact
options = { autofocusNoSpellcheckerOptions }
value = { value }
onChange = { onChange }
/>
) ;
} ; Puede incluir mapas clave utilizando el accesorio extraKeys . Lea más en Codemirror Extra Keys
export const UpdateableByHotKeys = ( ) => {
const extraKeys = useMemo < KeyMap > ( ( ) => {
return {
Up : function ( cm ) {
cm . replaceSelection ( " surprise. " ) ;
} ,
Down : function ( cm ) {
cm . replaceSelection ( " surprise again! " ) ;
} ,
} ;
} , [ ] ) ;
const [ value , setValue ] = useState ( "initial" ) ;
const onChange = ( value : string ) => setValue ( value ) ;
return (
< SimpleMdeReact value = { value } onChange = { onChange } extraKeys = { extraKeys } />
) ;
} ; import ReactDOMServer from "react-dom/server" ;
export const CustomPreview = ( ) => {
const customRendererOptions = useMemo ( ( ) => {
return {
previewRender ( ) {
return ReactDOMServer . renderToString (
< ReactMarkdown
source = { text }
renderers = { {
CodeBlock : CodeRenderer ,
Code : CodeRenderer ,
} }
/>
) ;
} ,
} as SimpleMDE . Options ;
} , [ ] ) ;
return (
< div >
< h4 > Custom preview </ h4 >
< SimpleMdeReact options = { customRendererOptions } />
</ div >
) ;
} ;Vea la lista completa de eventos aquí
import { SimpleMdeReact } from "react-simplemde-editor" ;
import type { SimpleMdeToCodemirrorEvents } from "react-simplemde-editor" ;
export const CustomEventListeners = ( ) => {
const [ value , setValue ] = useState ( "Initial value" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
// Make sure to always `useMemo` all the `options` and `events` props to ensure best performance!
const events = useMemo ( ( ) => {
return {
focus : ( ) => console . log ( value ) ,
} as SimpleMdeToCodemirrorEvents ;
} , [ ] ) ;
return < SimpleMdeReact events = { events } value = { value } onChange = { onChange } /> ;
} ; export const Autosaving = ( ) => {
const delay = 1000 ;
const autosavedValue = localStorage . getItem ( `smde_demo` ) || "Initial value" ;
const anOptions = useMemo ( ( ) => {
return {
autosave : {
enabled : true ,
uniqueId : "demo" ,
delay ,
} ,
} ;
} , [ delay ] ) ;
return (
< SimpleMdeReact id = "demo" value = { autosavedValue } options = { anOptions } />
) ;
} ;easymde , codemirror o cursor para poder manipularlo. export const GetDifferentInstances = ( ) => {
// simple mde
const [ simpleMdeInstance , setMdeInstance ] = useState < SimpleMDE | null > ( null ) ;
const getMdeInstanceCallback = useCallback ( ( simpleMde : SimpleMDE ) => {
setMdeInstance ( simpleMde ) ;
} , [ ] ) ;
useEffect ( ( ) => {
simpleMdeInstance &&
console . info ( "Hey I'm editor instance!" , simpleMdeInstance ) ;
} , [ simpleMdeInstance ] ) ;
// codemirror
const [ codemirrorInstance , setCodemirrorInstance ] = useState < Editor | null > (
null
) ;
const getCmInstanceCallback = useCallback ( ( editor : Editor ) => {
setCodemirrorInstance ( editor ) ;
} , [ ] ) ;
useEffect ( ( ) => {
codemirrorInstance &&
console . info ( "Hey I'm codemirror instance!" , codemirrorInstance ) ;
} , [ codemirrorInstance ] ) ;
// line and cursor
const [ lineAndCursor , setLineAndCursor ] = useState < Position | null > ( null ) ;
const getLineAndCursorCallback = useCallback ( ( position : Position ) => {
setLineAndCursor ( position ) ;
} , [ ] ) ;
useEffect ( ( ) => {
lineAndCursor &&
console . info ( "Hey I'm line and cursor info!" , lineAndCursor ) ;
} , [ lineAndCursor ] ) ;
return (
< div >
< h4 > Getting instance of Mde and codemirror and line and cursor info </ h4 >
< SimpleMdeReact
value = "Go to console to see stuff logged"
getMdeInstance = { getMdeInstanceCallback }
getCodemirrorInstance = { getCmInstanceCallback }
getLineAndCursor = { getLineAndCursorCallback }
/>
</ div >
) ;
} ;Así es como lo haces. Requiere simulacro de ciertas piezas del navegador para funcionar, pero este es todo un ejemplo.
import { act , render , screen } from "@testing-library/react" ;
import { useState } from "react" ;
import { SimpleMdeReact } from "react-simplemde-editor" ;
import userEvent from "@testing-library/user-event" ;
// @ts-ignore
Document . prototype . createRange = function ( ) {
return {
setEnd : function ( ) { } ,
setStart : function ( ) { } ,
getBoundingClientRect : function ( ) {
return { right : 0 } ;
} ,
getClientRects : function ( ) {
return {
length : 0 ,
left : 0 ,
right : 0 ,
} ;
} ,
} ;
} ;
const Editor = ( ) => {
const [ value , setValue ] = useState ( "" ) ;
return < SimpleMdeReact value = { value } onChange = { setValue } /> ;
} ;
describe ( "Renders" , ( ) => {
it ( "succesfully" , async ( ) => {
act ( ( ) => {
render ( < Editor /> ) ;
} ) ;
const editor = await screen . findByRole ( "textbox" ) ;
userEvent . type ( editor , "hello" ) ;
expect ( screen . getByText ( "hello" ) ) . toBeDefined ( ) ;
} ) ;
} ) ; export interface SimpleMDEReactProps
extends Omit < React . HTMLAttributes < HTMLDivElement > , "onChange" > {
id ?: string ;
onChange ?: ( value : string , changeObject ?: EditorChange ) => void ;
value ?: string ;
extraKeys ?: KeyMap ;
options ?: SimpleMDE . Options ;
events ?: SimpleMdeToCodemirrorEvents ;
getMdeInstance ?: GetMdeInstance ;
getCodemirrorInstance ?: GetCodemirrorInstance ;
getLineAndCursor ?: GetLineAndCursor ;
placeholder ?: string ;
textareaProps ?: Omit <
React . HTMLAttributes < HTMLTextAreaElement > ,
"id" | "style" | "placeholder"
> ;
} default - SimpleMderAct
SimpleMdeReact : igual que default pero nombrado
Tipos:
SimpleMdeReactProps : accesorios del componente
DOMEvent : ciertos eventos que se utilizan para obtener eventos exportados a continuación
CopyEvents : solo copia eventos de CodeMirror
GlobalEvents : algunos otros eventos globales de CodeMirror
DefaultEvent : función de controlador de eventos CodeMirror predeterminado
IndexEventsSignature : firma de índice que espera una cadena como clave y devuelve DefaultEvent
SimpleMdeToCodemirrorEvents : eventos diseñados manualmente (basados en @types/[email protected] que easymde usa internamente) + todos los anteriores fusionados en el mapeo completo entre los nombres de eventos de Codemirror y los manejadores reales para accesorio events
GetMdeInstance - Firma de la función de devolución de llamada que recupera la instancia de MDE
GetCodemirrorInstance : firma de la función de devolución de llamada que recupera la instancia de CodeMirror
GetLineAndCursor - Firma de la función de devolución de llamada que recupera la información de la línea y el cursor
simplemde . Posibles cambios de ruptura, así que llegué a la versión a V4.simplemde/dist/simplemde.min.css ahora será easymde/dist/easymde.min.css initialValue se ha eliminado y reemplazado con un accesorio value , lo que permite que los cambios directos al valor se realicen después de que el componente se monta.La versión 1.0 no tenía opciones de simplemde bien configuradas, este ReadMe refleja los cambios realizados para incluir mejor opciones. Este sigue siendo un proyecto muy nuevo. Las pruebas, los comentarios y los PR son bienvenidos y apreciados.