
一個帶有預覽的簡單標記編輯器,並使用React.js和Typescript實施。此React組件旨在提供一個簡單的Markdown編輯器和語法突出顯示支持。這是基於textarea封裝的,因此它不取決於任何現代代碼編輯器,例如ACS,Codemirror,Monaco等。
textarea封裝,不取決於任何現代代碼編輯器。uiw組件庫。npm i @uiw/react-md-editor或者
yarn add @uiw/react-md-editor import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!**" ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
/>
< MDEditor . Markdown source = { value } style = { { whiteSpace : 'pre-wrap' } } />
</ div >
) ;
}支持CSS風格
使用html註釋<!--rehype:xxx-->讓Markdown支持樣式自定義。
## Title
<!-- rehype:style=display: flex; height: 230px; align-items: center; justify-content: center; font-size: 38px; -->
Markdown Supports ** Style ** <!-- rehype:style=color: red; -->通過HTML註釋忽略內容顯示
在github readme中顯示,在html中排除。
# Hello World
<!-- rehype:ignore:start --> Hello World <!-- rehype:ignore:end -->
Good!輸出:
< h1 > Hello World </ h1 >
< p > Good! </ p >請注意,如果您不完全信任您的作者,則需要進行消毒。否則,您的應用程序容易受到XSS的影響。這可以通過添加rehype-sanitize作為插件來實現。
import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
import rehypeSanitize from "rehype-sanitize" ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( `**Hello world!!!** <IFRAME SRC="javascript:javascript:alert(window.origin);"></IFRAME>` ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
previewOptions = { {
rehypePlugins : [ [ rehypeSanitize ] ] ,
} }
/>
</ div >
) ;
}以下示例可以幫助您排除代碼突出顯示代碼中包含在捆綁包中。 @uiw/react-md-editor/nohighlight組件不包含代碼突出顯示軟件包,rehype-prism-plus ,,,,highlightEnable 和showLineNumbers功能將不再起作用。 (#586) highlight line
import React from "react" ;
import MDEditor from '@uiw/react-md-editor/nohighlight' ;
const code = `**Hello world!!!**
```js
function demo() {}
```
`
export default function App ( ) {
const [ value , setValue ] = React . useState ( code ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
/>
< MDEditor . Markdown source = { value } style = { { whiteSpace : 'pre-wrap' } } />
</ div >
) ;
}“下面是一個示例,為編輯器設置了placeholder ,並將最大輸入字符長度定義為10字符。”
import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "" ) ;
return (
< MDEditor
value = { value }
onChange = { setValue }
textareaProps = { {
placeholder : 'Please enter Markdown text' ,
maxLength : 10
} }
/>
) ;
} import React , { useState } from "react" ;
import MDEditor , { commands } from '@uiw/react-md-editor' ;
const title3 = {
name : 'title3' ,
keyCommand : 'title3' ,
buttonProps : { 'aria-label' : 'Insert title3' } ,
icon : (
< svg width = "12" height = "12" viewBox = "0 0 520 520" >
< path fill = "currentColor" d = "M15.7083333,468 C7.03242448,468 0,462.030833 0,454.666667 L0,421.333333 C0,413.969167 7.03242448,408 15.7083333,408 L361.291667,408 C369.967576,408 377,413.969167 377,421.333333 L377,454.666667 C377,462.030833 369.967576,468 361.291667,468 L15.7083333,468 Z M21.6666667,366 C9.69989583,366 0,359.831861 0,352.222222 L0,317.777778 C0,310.168139 9.69989583,304 21.6666667,304 L498.333333,304 C510.300104,304 520,310.168139 520,317.777778 L520,352.222222 C520,359.831861 510.300104,366 498.333333,366 L21.6666667,366 Z M136.835938,64 L136.835937,126 L107.25,126 L107.25,251 L40.75,251 L40.75,126 L-5.68434189e-14,126 L-5.68434189e-14,64 L136.835938,64 Z M212,64 L212,251 L161.648438,251 L161.648438,64 L212,64 Z M378,64 L378,126 L343.25,126 L343.25,251 L281.75,251 L281.75,126 L238,126 L238,64 L378,64 Z M449.047619,189.550781 L520,189.550781 L520,251 L405,251 L405,64 L449.047619,64 L449.047619,189.550781 Z" />
</ svg >
) ,
execute : ( state , api ) => {
let modifyText = `### ${ state . selectedText } n` ;
if ( ! state . selectedText ) {
modifyText = `### ` ;
}
api . replaceSelection ( modifyText ) ;
} ,
} ;
const title2 = {
name : 'title2' ,
keyCommand : 'title2' ,
render : ( command , disabled , executeCommand ) => {
return (
< button
aria-label = "Insert title2"
disabled = { disabled }
onClick = { ( evn ) => {
// evn.stopPropagation();
executeCommand ( command , command . groupName )
} }
>
< svg width = "12" height = "12" viewBox = "0 0 520 520" >
< path fill = "currentColor" d = "M15.7083333,468 C7.03242448,468 0,462.030833 0,454.666667 L0,421.333333 C0,413.969167 7.03242448,408 15.7083333,408 L361.291667,408 C369.967576,408 377,413.969167 377,421.333333 L377,454.666667 C377,462.030833 369.967576,468 361.291667,468 L15.7083333,468 Z M21.6666667,366 C9.69989583,366 0,359.831861 0,352.222222 L0,317.777778 C0,310.168139 9.69989583,304 21.6666667,304 L498.333333,304 C510.300104,304 520,310.168139 520,317.777778 L520,352.222222 C520,359.831861 510.300104,366 498.333333,366 L21.6666667,366 Z M136.835938,64 L136.835937,126 L107.25,126 L107.25,251 L40.75,251 L40.75,126 L-5.68434189e-14,126 L-5.68434189e-14,64 L136.835938,64 Z M212,64 L212,251 L161.648438,251 L161.648438,64 L212,64 Z M378,64 L378,126 L343.25,126 L343.25,251 L281.75,251 L281.75,126 L238,126 L238,64 L378,64 Z M449.047619,189.550781 L520,189.550781 L520,251 L405,251 L405,64 L449.047619,64 L449.047619,189.550781 Z" />
</ svg >
</ button >
)
} ,
execute : ( state , api ) => {
let modifyText = `## ${ state . selectedText } n` ;
if ( ! state . selectedText ) {
modifyText = `## ` ;
}
api . replaceSelection ( modifyText ) ;
} ,
}
function SubChildren ( { close , execute , getState , textApi , dispatch } ) {
const [ value , setValue ] = useState ( '' )
const insert = ( ) => {
console . log ( 'value:::' , value )
textApi . replaceSelection ( value )
}
return (
< div style = { { width : 120 , padding : 10 } } >
< div > My Custom Toolbar </ div >
< input type = "text" onChange = { ( e ) => setValue ( e . target . value ) } />
< button
type = "button"
onClick = { ( ) => {
dispatch ( { $value : '~~~~~~' } )
console . log ( '> execute: >>>>>' , getState ( ) )
} }
>
State
</ button >
< button type = "button" onClick = { insert } > Insert </ button >
< button type = "button" onClick = { ( ) => close ( ) } > Close </ button >
< button type = "button" onClick = { ( ) => execute ( ) } > Execute </ button >
</ div >
) ;
}
const subChild = {
name : 'update' ,
groupName : 'update' ,
icon : (
< svg viewBox = "0 0 1024 1024" width = "12" height = "12" >
< path fill = "currentColor" d = "M716.8 921.6a51.2 51.2 0 1 1 0 102.4H307.2a51.2 51.2 0 1 1 0-102.4h409.6zM475.8016 382.1568a51.2 51.2 0 0 1 72.3968 0l144.8448 144.8448a51.2 51.2 0 0 1-72.448 72.3968L563.2 541.952V768a51.2 51.2 0 0 1-45.2096 50.8416L512 819.2a51.2 51.2 0 0 1-51.2-51.2v-226.048l-57.3952 57.4464a51.2 51.2 0 0 1-67.584 4.2496l-4.864-4.2496a51.2 51.2 0 0 1 0-72.3968zM512 0c138.6496 0 253.4912 102.144 277.1456 236.288l10.752 0.3072C924.928 242.688 1024 348.0576 1024 476.5696 1024 608.9728 918.8352 716.8 788.48 716.8a51.2 51.2 0 1 1 0-102.4l8.3968-0.256C866.2016 609.6384 921.6 550.0416 921.6 476.5696c0-76.4416-59.904-137.8816-133.12-137.8816h-97.28v-51.2C691.2 184.9856 610.6624 102.4 512 102.4S332.8 184.9856 332.8 287.488v51.2H235.52c-73.216 0-133.12 61.44-133.12 137.8816C102.4 552.96 162.304 614.4 235.52 614.4l5.9904 0.3584A51.2 51.2 0 0 1 235.52 716.8C105.1648 716.8 0 608.9728 0 476.5696c0-132.1984 104.8064-239.872 234.8544-240.2816C258.5088 102.144 373.3504 0 512 0z" />
</ svg >
) ,
children : ( props ) => < SubChildren { ... props } /> ,
execute : ( state , api ) => {
console . log ( '>>>>>>update>>>>>' , state )
} ,
buttonProps : { 'aria-label' : 'Insert title' }
}
export default function App ( ) {
const [ value , setValue ] = React . useState ( "Hello Markdown! `Tab` key uses default behavior" ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
commands = { [
// Custom Toolbars
title3 , title2 ,
commands . group ( [ commands . title1 , commands . title2 , commands . title3 , commands . title4 , commands . title5 , commands . title6 ] , {
name : 'title' ,
groupName : 'title' ,
buttonProps : { 'aria-label' : 'Insert title' }
} ) ,
commands . divider ,
commands . group ( [ ] , subChild ) ,
] }
/>
</ div >
) ;
}使用commands和extraCommands Props自定義工具欄。
import React from "react" ;
import MDEditor , { commands } from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "Hello Markdown! `Tab` key uses default behavior" ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
preview = "edit"
commands = { [
commands . codeEdit , commands . codePreview
] }
extraCommands = { [
commands . group ( [ commands . title1 , commands . title2 , commands . title3 , commands . title4 , commands . title5 , commands . title6 ] , {
name : 'title' ,
groupName : 'title' ,
buttonProps : { 'aria-label' : 'Insert title' }
} ) ,
commands . divider ,
commands . group ( [ ] , {
name : 'update' ,
groupName : 'update' ,
icon : (
< svg viewBox = "0 0 1024 1024" width = "12" height = "12" >
< path fill = "currentColor" d = "M716.8 921.6a51.2 51.2 0 1 1 0 102.4H307.2a51.2 51.2 0 1 1 0-102.4h409.6zM475.8016 382.1568a51.2 51.2 0 0 1 72.3968 0l144.8448 144.8448a51.2 51.2 0 0 1-72.448 72.3968L563.2 541.952V768a51.2 51.2 0 0 1-45.2096 50.8416L512 819.2a51.2 51.2 0 0 1-51.2-51.2v-226.048l-57.3952 57.4464a51.2 51.2 0 0 1-67.584 4.2496l-4.864-4.2496a51.2 51.2 0 0 1 0-72.3968zM512 0c138.6496 0 253.4912 102.144 277.1456 236.288l10.752 0.3072C924.928 242.688 1024 348.0576 1024 476.5696 1024 608.9728 918.8352 716.8 788.48 716.8a51.2 51.2 0 1 1 0-102.4l8.3968-0.256C866.2016 609.6384 921.6 550.0416 921.6 476.5696c0-76.4416-59.904-137.8816-133.12-137.8816h-97.28v-51.2C691.2 184.9856 610.6624 102.4 512 102.4S332.8 184.9856 332.8 287.488v51.2H235.52c-73.216 0-133.12 61.44-133.12 137.8816C102.4 552.96 162.304 614.4 235.52 614.4l5.9904 0.3584A51.2 51.2 0 0 1 235.52 716.8C105.1648 716.8 0 608.9728 0 476.5696c0-132.1984 104.8064-239.872 234.8544-240.2816C258.5088 102.144 373.3504 0 512 0z" />
</ svg >
) ,
children : ( { close , execute , getState , textApi } ) => {
return (
< div style = { { width : 120 , padding : 10 } } >
< div > My Custom Toolbar </ div >
< button type = "button" onClick = { ( ) => console . log ( '> execute: >>>>>' , getState ( ) ) } > State </ button >
< button type = "button" onClick = { ( ) => close ( ) } > Close </ button >
< button type = "button" onClick = { ( ) => execute ( ) } > Execute </ button >
</ div >
) ;
} ,
execute : ( state , api ) => {
console . log ( '>>>>>>update>>>>>' , state )
} ,
buttonProps : { 'aria-label' : 'Insert title' }
} ) ,
commands . divider , commands . fullscreen
] }
/>
</ div >
) ;
}重新渲染toolbar元素。
import React from "react" ;
import MDEditor , { commands } from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "Hello Markdown! `Tab` key uses default behavior" ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
onChange = { setValue }
preview = "edit"
components = { {
toolbar : ( command , disabled , executeCommand ) => {
if ( command . keyCommand === 'code' ) {
return (
< button
aria-label = "Insert code"
disabled = { disabled }
onClick = { ( evn ) => {
evn . stopPropagation ( ) ;
executeCommand ( command , command . groupName )
} }
>
Code
</ button >
)
}
}
} }
/>
</ div >
) ;
}自定義預覽命令工具
import React , { useContext } from "react" ;
import MDEditor , { commands , EditorContext } from "@uiw/react-md-editor" ;
const Button = ( ) => {
const { preview , dispatch } = useContext ( EditorContext ) ;
const click = ( ) => {
dispatch ( {
preview : preview === "edit" ? "preview" : "edit"
} ) ;
} ;
if ( preview === "edit" ) {
return (
< svg width = "12" height = "12" viewBox = "0 0 520 520" onClick = { click } >
< polygon
fill = "currentColor"
points = "0 71.293 0 122 319 122 319 397 0 397 0 449.707 372 449.413 372 71.293"
/>
< polygon
fill = "currentColor"
points = "429 71.293 520 71.293 520 122 481 123 481 396 520 396 520 449.707 429 449.413"
/>
</ svg >
) ;
}
return (
< svg width = "12" height = "12" viewBox = "0 0 520 520" onClick = { click } >
< polygon
fill = "currentColor"
points = "0 71.293 0 122 38.023 123 38.023 398 0 397 0 449.707 91.023 450.413 91.023 72.293"
/>
< polygon
fill = "currentColor"
points = "148.023 72.293 520 71.293 520 122 200.023 124 200.023 397 520 396 520 449.707 148.023 450.413"
/>
</ svg >
) ;
} ;
const codePreview = {
name : "preview" ,
keyCommand : "preview" ,
value : "preview" ,
icon : < Button />
} ;
const Disable = ( ) => {
const { preview , dispatch } = useContext ( EditorContext ) ;
return (
< button disabled = { preview === "preview" } >
< svg viewBox = "0 0 16 16" width = "12px" height = "12px" >
< path
d = "M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8Zm.9 13H7v-1.8h1.9V13Zm-.1-3.6v.5H7.1v-.6c.2-2.1 2-1.9 1.9-3.2.1-.7-.3-1.1-1-1.1-.8 0-1.2.7-1.2 1.6H5c0-1.7 1.2-3 2.9-3 2.3 0 3 1.4 3 2.3.1 2.3-1.9 2-2.1 3.5Z"
fill = "currentColor"
/>
</ svg >
</ button >
)
}
const customButton = {
name : "disable" ,
keyCommand : "disable" ,
value : "disable" ,
icon : < Disable />
}
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!**" ) ;
return (
< div className = "container" >
< div > The system automatically sets the theme </ div >
< MDEditor
value = { value }
preview = "edit"
extraCommands = { [ codePreview , customButton , commands . fullscreen ] }
onChange = { ( val ) => setValue ( val ) }
/>
</ div >
) ;
}添加幫助命令工具
import React , { useContext } from "react" ;
import MDEditor , { commands } from "@uiw/react-md-editor" ;
const help = {
name : "help" ,
keyCommand : "help" ,
buttonProps : { "aria-label" : "Insert help" } ,
icon : (
< svg viewBox = "0 0 16 16" width = "12px" height = "12px" >
< path
d = "M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8Zm.9 13H7v-1.8h1.9V13Zm-.1-3.6v.5H7.1v-.6c.2-2.1 2-1.9 1.9-3.2.1-.7-.3-1.1-1-1.1-.8 0-1.2.7-1.2 1.6H5c0-1.7 1.2-3 2.9-3 2.3 0 3 1.4 3 2.3.1 2.3-1.9 2-2.1 3.5Z"
fill = "currentColor"
/>
</ svg >
) ,
execute : ( state , api ) => {
window . open ( "https://www.markdownguide.org/basic-syntax/" , "_blank" ) ;
}
} ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!**" ) ;
return (
< MDEditor
value = { value }
preview = "edit"
commands = { [ ... commands . getCommands ( ) , help ] }
onChange = { ( val ) => setValue ( val ) }
/>
) ;
}國際化示例,您可以參考國際化commands-cn 。
import React , { useContext } from "react" ;
import MDEditor , { commands } from "@uiw/react-md-editor" ;
import { getCommands , getExtraCommands } from "@uiw/react-md-editor/commands-cn" ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!**" ) ;
return (
< MDEditor
value = { value }
preview = "edit"
commands = { [ ... getCommands ( ) ] }
extraCommands = { [ ... getExtraCommands ( ) ] }
onChange = { ( val ) => setValue ( val ) }
/>
) ;
} body . w-md-editor-text-pre > code ,
body . w-md-editor-text-input {
font-size : 23 px !important ;
line-height : 24 px !important ;
}可以通過minHeight={100}調整初始高度。 Dragbar將自動過期。您可以通過visibleDragbar={false}隱藏“拖動”按鈕
import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!**" ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
height = "100%"
// minHeight={50}
visibleDragbar = { false }
onChange = { setValue }
/>
</ div >
) ;
} import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( "**Hello world!!!** <style>body{display:none;}</style> " ) ;
return (
< div className = "container" >
< MDEditor
value = { value }
height = "100%"
previewOptions = { {
disallowedElements : [ 'style' ] ,
} }
visibleDragbar = { false }
onChange = { setValue }
/>
</ div >
) ;
} import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
export default function App ( ) {
return (
< div className = "container" >
< MDEditor . Markdown source = "Hello Markdown!" />
</ div >
) ;
}Katex是一個快速,易於使用的JavaScript庫,用於網絡上的Tex Math渲染,我們通過KaTeX進行數學渲染。
以下示例是Codesandbox中的預覽。
配x 升級V2到V3 D025430
npm install katex import React from "react" ;
import MDEditor from '@uiw/react-md-editor' ;
import { getCodeString } from 'rehype-rewrite' ;
import katex from 'katex' ;
import 'katex/dist/katex.css' ;
const mdKaTeX = `This is to display the
`$$c = \pm\sqrt{a^2 + b^2}$$`
in one line
```KaTeX
c = \pm\sqrt{a^2 + b^2}
```
` ;
export default function App ( ) {
const [ value , setValue ] = React . useState ( mdKaTeX ) ;
return (
< MDEditor
value = { value }
onChange = { ( val ) => setValue ( val ) }
previewOptions = { {
components : {
code : ( { children = [ ] , className , ... props } ) => {
if ( typeof children === 'string' && / ^$$(.*)$$ / . test ( children ) ) {
const html = katex . renderToString ( children . replace ( / ^$$(.*)$$ / , '$1' ) , {
throwOnError : false ,
} ) ;
return < code dangerouslySetInnerHTML = { { __html : html } } style = { { background : 'transparent' } } /> ;
}
const code = props . node && props . node . children ? getCodeString ( props . node . children ) : children ;
if (
typeof code === 'string' &&
typeof className === 'string' &&
/ ^language-katex / . test ( className . toLocaleLowerCase ( ) )
) {
const html = katex . renderToString ( code , {
throwOnError : false ,
} ) ;
return < code style = { { fontSize : '150%' } } dangerouslySetInnerHTML = { { __html : html } } /> ;
}
return < code className = { String ( className ) } > { children } </ code > ;
} ,
} ,
} }
/>
) ;
} import React , { useState } from "react" ;
import MDEditor , { commands , ICommand , TextState , TextAreaTextApi } from "@uiw/react-md-editor" ;
import domToImage from "dom-to-image" ;
const textToImage : ICommand = {
name : "Text To Image" ,
keyCommand : "text2image" ,
buttonProps : { "aria-label" : "Insert title3" } ,
icon : (
< svg width = "12" height = "12" viewBox = "0 0 20 20" >
< path fill = "currentColor" d = "M15 9c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4-7H1c-.55 0-1 .45-1 1v14c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 13l-6-5-2 2-4-5-4 8V4h16v11z" > </ path >
</ svg >
) ,
execute : ( state : TextState , api : TextAreaTextApi ) => {
const dom = document . getElementsByClassName ( "gooooooooo" ) [ 0 ] ;
if ( dom ) {
domToImage . toJpeg ( dom , { } ) . then ( ( dataUrl ) => {
const link = document . createElement ( "a" ) ;
link . download = "image.jpg" ;
link . href = dataUrl ;
link . click ( ) ;
} ) ;
}
}
} ;
export default function App ( ) {
const [ value , setValue ] = useState ( '**Hello world!!!**' ) ;
console . log ( 'value::' , value )
return (
< div className = "container" >
< MDEditor
className = "gooooooooo"
onChange = { ( newValue = "" ) => setValue ( newValue ) }
value = { value }
commands = { [
textToImage ,
commands . divider
] }
/>
</ div >
) ;
}以類似於Markdown的方式將美人魚從文本的生成圖和流程圖生成
npm install mermaid import React , { useState , useRef , useEffect , Fragment , useCallback } from "react" ;
import MDEditor from "@uiw/react-md-editor" ;
import { getCodeString } from 'rehype-rewrite' ;
import mermaid from "mermaid" ;
const mdMermaid = `The following are some examples of the diagrams, charts and graphs that can be made using Mermaid and the Markdown-inspired text specific to it.
```mermaid
graph TD
A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
```
```mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
```
` ;
const randomid = ( ) => parseInt ( String ( Math . random ( ) * 1e15 ) , 10 ) . toString ( 36 ) ;
const Code = ( { inline , children = [ ] , className , ... props } ) => {
const demoid = useRef ( `dome ${ randomid ( ) } ` ) ;
const [ container , setContainer ] = useState ( null ) ;
const isMermaid =
className && / ^language-mermaid / . test ( className . toLocaleLowerCase ( ) ) ;
const code = children
? getCodeString ( props . node . children )
: children [ 0 ] || "" ;
useEffect ( ( ) => {
if ( container && isMermaid && demoid . current && code ) {
mermaid
. render ( demoid . current , code )
. then ( ( { svg , bindFunctions } ) => {
container . innerHTML = svg ;
if ( bindFunctions ) {
bindFunctions ( container ) ;
}
} )
. catch ( ( error ) => {
console . log ( "error:" , error ) ;
} ) ;
}
} , [ container , isMermaid , code , demoid ] ) ;
const refElement = useCallback ( ( node ) => {
if ( node !== null ) {
setContainer ( node ) ;
}
} , [ ] ) ;
if ( isMermaid ) {
return (
< Fragment >
< code id = { demoid . current } style = { { display : "none" } } />
< code className = { className } ref = { refElement } data-name = "mermaid" />
</ Fragment >
) ;
}
return < code className = { className } > { children } </ code > ;
} ;
export default function App ( ) {
const [ value , setValue ] = useState ( mdMermaid ) ;
return (
< MDEditor
onChange = { ( newValue = "" ) => setValue ( newValue ) }
textareaProps = { {
placeholder : "Please enter Markdown text"
} }
height = { 500 }
value = { value }
previewOptions = { {
components : {
code : Code
}
} }
/>
) ;
}在NextJ中使用示例。 #52 #224
npm install next-remove-imports
npm install @uiw/[email protected] // next.config.js
const removeImports = require ( 'next-remove-imports' ) ( ) ;
module . exports = removeImports ( { } ) ; import "@uiw/react-md-editor/markdown-editor.css" ;
import "@uiw/react-markdown-preview/markdown.css" ;
import dynamic from "next/dynamic" ;
import { useState } from "react" ;
import * as commands from "@uiw/react-md-editor/commands"
const MDEditor = dynamic (
( ) => import ( "@uiw/react-md-editor" ) ,
{ ssr : false }
) ;
function HomePage ( ) {
const [ value , setValue ] = useState ( "**Hello world!!!**" ) ;
return (
< div >
< MDEditor value = { value } onChange = { setValue } />
</ div >
) ;
}
export default HomePage ;默認情況下,根據系統自動切換dark-mode 。如果您需要手動切換,只需設置Body的data-color-mode="dark"參數即可。
< html data-color-mode =" dark " > document . documentElement . setAttribute ( 'data-color-mode' , 'dark' )
document . documentElement . setAttribute ( 'data-color-mode' , 'light' )通過添加.wmde-markdown-var選擇器繼承自定義顏色變量。用data-color-mode="light" 。
< div data-color-mode =" light " >
< div className =" wmde-markdown-var " > </ div >
< MDEditor source =" Hello World! " />
</ div >value: string :標記值。onChange?: (value?: string, event?: React.ChangeEvent<HTMLTextAreaElement>, state?: ContextStore) : onChange事件的事件處理程序。onHeightChange?: ((value?: CSSProperties['height'], oldValue?: CSSProperties['height'], state?: ContextStore) :編輯器高度更改偵聽器。onStatistics?: (data: Statistics) => void;有關統計編輯器的一些數據。commands?: ICommand[] :一個ICommand的數組,每個數組都包含一個commands屬性。如果未指定命令,將使用默認值。在下面的更多詳細信息中解釋了命令。commandsFilter?: (command: ICommand, isExtra: boolean) => false | ICommand :過濾或修改您的命令。extraCommands?: ICommand[] :顯示在工具欄的右側。autoFocus?: true :可以用來使Markdown Editor專注於初始化。previewOptions?: ReactMarkdown.ReactMarkdownProps :這是RESET @uiw/react-markdown-preview設置。textareaProps?: TextareaHTMLAttributes :設置與textarea相關的道具。renderTextarea?: (props, opts) => JSX.Element;@deprecated請使用renderTextareacomponents 。使用div替換文本方面或重新渲染的文本方面。 #193components :重新渲染文本/工具欄元素。 #419textarea使用Div替換Textarea或重新渲染Textareatoolbar覆蓋默認命令元素。 toolbar < command[].renderpreview自定義標記預覽。 #429height?: number=200 :編輯器的高度。配xheight參數百分比時, Dragbar無效。visibleDragbar?: boolean=true :顯示拖放工具。設置編輯器的高度。highlightEnable?: boolean=true :禁用編輯區域代碼突出顯示。該值是false ,它增加了編輯速度。fullscreen?: boolean=false :顯示Markdown預覽。overflow?: boolean=true :禁用fullscreen設置身體樣式preview?: 'live' | 'edit' | 'preview' :默認值live ,顯示標記預覽。maxHeight?: number=1200 :最大阻力高度。 visibleDragbar=true值有效。minHeight?: number=100 :最小阻力高度。 visibleDragbar=true值有效。tabSize?: number=2 :按下選項卡鍵時要插入的字符數。默認2空格。defaultTabEnable?: boolean=false :如果false ,則tab鍵”將選項卡字符插入文本方面。如果為true ,則tab鍵執行默認行為,例如焦點轉移到下一個元素。hideToolbar?: boolean=false :隱藏工具欄的選項。enableScroll?: boolean=true :是否啟用滾動。$ npm install # Installation dependencies
$ npm run build # Compile all package@uiw/react-md-editor包: $ cd core
# listen to the component compile and output the .js file
# listen for compilation output type .d.ts file
$ npm run watch # Monitor the compiled package `@uiw/react-md-editor`npm run start與往常一樣,感謝我們出色的貢獻者!
由貢獻者製成。
根據MIT許可獲得許可。