
React.jsおよびTypeScriptで実装されたプレビューを備えたシンプルなMarkdownエディター。このReactコンポーネントは、シンプルなマークダウンエディターにSyntaxの強調表示サポートを提供することを目的としています。これは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-->を使用して、マークダウンスタイルのカスタマイズをサポートします。
## 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コマンドの小道具でツールバーをカスタマイズします。
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は、Web上でTex Mathレンダリングのための高速で使いやすいJavaScriptライブラリであり、 KaTeXを通じて数学レンダリングを実行します。
次の例は、CodeSandBoxのプレビューです。
ショ和 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 >
) ;
}マークダウンと同様の方法でテキストから図とフローチャートの生成に人魚を使用する
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
}
} }
/>
) ;
}NextJSの例を使用してください。 #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システムに応じて自動的に切り替えられます。手動で切り替える必要がある場合は、ボディの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[] :それぞれにcommandsプロパティを含むICommandの配列。コマンドが指定されていない場合、デフォルトが使用されます。コマンドについては、以下の詳細について説明します。commandsFilter?: (command: ICommand, isExtra: boolean) => false | ICommand :コマンドをフィルタリングまたは変更します。extraCommands?: ICommand[] :ツールバーの右側に表示されます。autoFocus?: true : Markdown Editor初期化に焦点を合わせるために使用できます。previewOptions?: ReactMarkdown.ReactMarkdownProps :これは @uiw/React-markdown-preview設定です。textareaProps?: TextareaHTMLAttributes : textarea関連小道具を設定します。renderTextarea?: (props, opts) => JSX.Element;@deprecated使用してくださいrenderTextareacomponents 。 Divを使用して、Textareaを交換するか、Textareaを再レンダリングします。 #193components :Textarea/Toolbar要素を再レンダリングします。 #419textarea Divを使用してTextareaを置き換えるか、Textareaを再レンダリングしますtoolbar 、デフォルトのコマンド要素をオーバーライドします。 toolbar < command[].renderpreviewカスタムマークダウンプレビュー。 #429height?: number=200 :編集者の高さ。ショ和Dragbar 、 heightパラメーターの割合の場合、無効です。visibleDragbar?: boolean=true :ドラッグアンドドロップツールを表示します。編集者の高さを設定します。highlightEnable?: boolean=true :編集局在コードの強調表示を無効にします。値はfalseで、編集速度が向上します。fullscreen?: boolean=false :マークダウンプレビューを表示します。overflow?: boolean=true : fullscreen設定ボディスタイルを無効にしますpreview?: 'live' | 'edit' | 'preview' :デフォルト値のlive 、マークダウンプレビューを表示します。maxHeight?: number=1200 :最大抗力高さ。 visibleDragbar=true値は有効です。minHeight?: number=100 :最小ドラッグ高さ。 visibleDragbar=true値は有効です。tabSize?: number=2 :Tabキーを押すときに挿入する文字の数。デフォルトの2スペース。defaultTabEnable?: boolean=false : falseの場合、 tabはタブ文字をTextareaに挿入します。 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ライセンスに基づいてライセンスされています。