React Composant Wrapper pour Easymde (la fourche Simplemde la plus fraîche).
Seulement deux dépendances, React (Peer) et Easymde (pair).
Construit par @ rip21?
easymde , codemirror ou cursor pour pouvoir la manipuler.Table des matières générée avec Markdown-Toc
>=16.8.2easymde maintenant une dépendance par les pairs, veuillez l'installer manuellementlabel Prop a été suppriméoptions doivent être mémorisées pour empêcher la création de nouvelles instances sur chaque rendu et d'autres liés à ces bogues (plus à ce sujet ci-dessous)ref , vous pouvez donc facilement accéder à div Wrapper en utilisant ref Prop.@babel/runtime ne sont plus inclus mais importés. npm install --save react-simplemde-editor easymde
Remarque: Vous devrez peut-être installer @babel/runtime , essayez sans cela, mais si vous n'avez aucun problème, vous ne devriez pas.
Démo hébergé
ou pour le voir localement:
git clone https://github.com/RIP21/react-simplemde-editor.git
cd react-simplemde-editor
yarn install
yarn demo
open browser at localhost:3000
Consultez le code de démonstration pour plus d'exemples.
Tous les exemples ci-dessous sont en dactylographie
Utilisation incontrôlée
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 } /> ;
} ; Vous pouvez définir une API des options Simplemde que vous transmettez en tant qu'accessoire options . Si vous utilisez TypeScript, il sera déduit par le compilateur.
Remarque: Si vous ne spécifiez pas un ID personnalisé, il générera automatiquement un ID pour vous.
Notez que vous devez useMemo options pour mémoriser afin qu'ils ne changent pas sur chaque remension! Cela affectera le comportement et les performances, car alors sur chaque rendu du parent qui rend SimpleMdeReact vous obtiendrez une nouvelle instance de l'éditeur, que vous voulez vraiment éviter! De plus, si vous modifiez options sur chaque changement value , vous perdrez la focalisation. Ainsi, mettez options en tant que const en dehors du composant, ou si options doivent être partiellement ou entièrement définies par props , assurez-vous d' useMemo en cas de composants fonctionnels / hooks, ou champ de classe pour les composants basés sur class . Un peu plus à ce sujet ici: # 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 }
/>
) ;
} ; Vous pouvez inclure des cartes clés à l'aide de l'hélice extraKeys . En savoir plus sur 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 >
) ;
} ;Voir la liste complète des événements ici
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 ou cursor pour pouvoir la manipuler. 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 >
) ;
} ;Voici comment vous le faites. Cela nécessite une simulation de certaines pièces de navigateur pour fonctionner, mais c'est un exemple complet.
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 - Simplemedereact
SimpleMdeReact - Identique default mais nommé
Types:
SimpleMdeReactProps - accessoires du composant
DOMEvent - Certains événements utilisés pour faire exporter des événements ci-dessous
CopyEvents - Copier uniquement les événements Codemirror
GlobalEvents - Quelques autres événements mondiaux de codeirror
DefaultEvent - Fonction de gestion de codemirror par défaut
IndexEventsSignature - Signature d'index qui attend la chaîne comme clé et renvoie DefaultEvent
SimpleMdeToCodemirrorEvents - Événements fabriqués manuellement (basé sur @types/[email protected] que easymde utilise en interne) + Tout ce qui précède fusionné en mappage entier entre les noms d'événements Codemirror et les gestionnaires réels pour events
GetMdeInstance - Signature de la fonction de rappel qui récupère l'instance MDE
GetCodemirrorInstance - Signature de la fonction de rappel qui récupère l'instance Codemirror
GetLineAndCursor - Signature de la fonction de rappel qui récupère les informations de ligne et de curseur
simplemde elle-même. Les changements de rupture possibles, j'ai donc heurté la version à V4.simplemde/dist/simplemde.min.css maintenant ce sera easymde/dist/easymde.min.css initialValue a été supprimée et remplacée par un accessoire value , permettant des modifications directes de la valeur après les montures du composant.La version 1.0 n'avait pas bien les options Simplemde bien configurées, ce ReadMe reflète les modifications apportées pour mieux inclure les options. C'est encore un tout nouveau projet. Les tests, les commentaires et les RP sont les bienvenus et appréciés.