React Component Purper для EasyMde (самая свежая вилка Simplemde).
Только две зависимости, реагировать (сверстник) и EasyMde (сверстник).
Построен @RIP21?
easymde , codemirror или cursor , чтобы иметь возможность манипулировать этим.Содержимое содержимого, сгенерированное с помощью Markdown-Toc
>=16.8.2easymde теперь зависимость от сверстников, пожалуйста, установите ее вручнуюlabel была удаленаoptions должны быть запоминаются, чтобы предотвратить создание новых экземпляров на каждом визуализации и других, связанных с этими ошибками (подробнее об этом ниже)ref , так что вы можете легко получить доступ к div Wrapper, используя ref PROP.@babel/runtime Helpers больше не вставлены, а импортированы. npm install --save react-simplemde-editor easymde
Примечание. Возможно, вам может потребоваться установить @babel/runtime , попробуйте без него, но если у вас нет проблем, то вы не должны.
Устроенный демонстрация
или увидеть его на местном уровне:
git clone https://github.com/RIP21/react-simplemde-editor.git
cd react-simplemde-editor
yarn install
yarn demo
open browser at localhost:3000
Посмотреть демо -код для получения дополнительных примеров.
Все примеры ниже приведены в TypeScript
Неконтролируемое использование
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 } /> ;
} ; Вы можете установить API параметров SimpleMde, которые вы передаете в качестве опоры options . Если вы используете TypeScript, он будет выведен компилятором.
ПРИМЕЧАНИЕ. Если вы не указаете пользовательский идентификатор, он автоматически генерирует идентификатор для вас.
Обратите внимание, что вам нужно useMemo , чтобы запомнить options , чтобы они не менялись на каждом ререндере! Это повлияет на поведение и производительность, потому что тогда на каждом рендеринге родителя, который отдает SimpleMdeReact , вы получите новый экземпляр редактора, которого вы определенно хотите избежать! Кроме того, если вы измените options при каждом изменении value , вы потеряете фокус. Таким образом, options поместите параметры как const за пределами компонента, или, если options должны быть частично или полностью установлены по props , обязательно обязательно для useMemo в случае функциональных компонентов/крючков или поле класса для компонентов на основе class . Немного больше об этом здесь: #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 }
/>
) ;
} ; Вы можете включить карты клавиш, используя поддержку extraKeys . Узнайте больше на 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 >
) ;
} ;См. Полный список событий здесь
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 или cursor , чтобы иметь возможность манипулировать этим. 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 >
) ;
} ;Вот как вы это делаете. Для работы требуется издеваться над некоторыми частями браузера, но это целый пример.
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 - SimpleMdereAct
SimpleMdeReact - так же, как и default , но назван
Типы:
SimpleMdeReactProps - реквизиты компонента
DOMEvent - определенные события, которые используются для экспорта событий ниже
CopyEvents - только копировать события Codemirror
GlobalEvents - Некоторые другие глобальные события Codemirror
DefaultEvent - по умолчанию функция обработчика событий Codemirror
IndexEventsSignature - Индексная подпись, которая ожидает String в качестве ключа и возвращает DefaultEvent
SimpleMdeToCodemirrorEvents - События вручную изготовления (на основе @types/[email protected] , которые easymde использует внутренне) + все вышеперечисленное, объединенное в целое отображение между именами событий Codemirror и фактическими обработками для events .
GetMdeInstance - Подпись функции обратного вызова, которая извлекает экземпляр MDE
GetCodemirrorInstance - Подпись функции обратного вызова, которая извлекает экземпляр Codemirror
GetLineAndCursor - подпись функции обратного вызова, которая получает информацию о строке и курсоре
simplemde . Возможные нарушения изменений, поэтому я наткнулся на версию в V4.simplemde/dist/simplemde.min.css теперь это будет easymde/dist/easymde.min.css initialValue была удалена и заменена на value , что позволяет прямым изменению значения, которое будет сделано после состава компонента.Версия 1.0 не имела настроенных параметров, которые хорошо настроены, это чтение отражает изменения, сделанные для лучшего включения вариантов. Это все еще очень новый проект. Тестирование, обратная связь и PRS приветствуются и ценятся.