React Component Preview Markdown Text ในเว็บเบราว์เซอร์ จำนวน CSS ที่น้อยที่สุดในการทำซ้ำรูปแบบการทำเครื่องหมาย GitHub เว็บไซต์เอกสารปัจจุบันถูกแปลงโดยใช้องค์ประกอบปฏิกิริยานี้
@v4$ npm install @uiw/react-markdown-preview --save import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
## MarkdownPreview
> todo: React component preview markdown text.
` ;
export default function Demo ( ) {
return (
< MarkdownPreview source = { source } style = { { padding : 16 } } />
)
} import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
## MarkdownPreview
## Header 2
### Header 3
` ;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
rehypeRewrite = { ( node , index , parent ) => {
if ( node . tagName === "a" && parent && / ^h(1|2|3|4|5|6) / . test ( parent . tagName ) ) {
parent . children = parent . children . slice ( 1 )
}
} }
/>
) ;
} ไวยากรณ์: ```jsx {1,4-5}
import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
```js {2}
function () {
console.log('hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello')
}
```
```js {2}
function () {
console.log('hello ')
}
```
` ;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
rehypeRewrite = { ( node , index , parent ) => {
if ( node . tagName === "a" && parent && / ^h(1|2|3|4|5|6) / . test ( parent . tagName ) ) {
parent . children = parent . children . slice ( 1 )
}
} }
/>
) ;
} ไวยากรณ์: ```jsx showLineNumbers {1,4-5}
import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
```js showLineNumbers
function () {
console.log('hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello')
}
```
```js showLineNumbers {2}
function () {
console.log('hello ')
}
```
` ;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
rehypeRewrite = { ( node , index , parent ) => {
if ( node . tagName === "a" && parent && / ^h(1|2|3|4|5|6) / . test ( parent . tagName ) ) {
parent . children = parent . children . slice ( 1 )
}
} }
/>
) ;
} import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
```js
function () {
console.log('hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello')
}
```
```js
function () {
console.log('hello ')
}
```
` ;
export default function Demo ( ) {
return (
< MarkdownPreview source = { source } style = { { padding : 16 } } />
) ;
} ตัวอย่างต่อไปนี้สามารถช่วยให้คุณ ไม่รวมรหัสที่เน้นรหัส จากการรวมอยู่ในชุดข้อมูล @uiw/react-markdown-preview/nohighlight Component ไม่มีแพ็คเกจไฮไลต์รหัสซ้ำ rehype-prism-plus , showLineNumbers และฟังก์ชั่น highlight line บรรทัดจะไม่ทำงานอีกต่อไป (#586)
import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview/nohighlight' ;
const source = `
```js
function () {
console.log('hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello')
}
```
```js
function () {
console.log('hello ')
}
```
` ;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
rehypeRewrite = { ( node , index , parent ) => {
if ( node . tagName === "a" && parent && / ^h(1|2|3|4|5|6) / . test ( parent . tagName ) ) {
parent . children = parent . children . slice ( 1 )
}
} }
/>
) ;
} ละเว้นการแสดงเนื้อหาผ่านความคิดเห็น HTML ที่แสดงใน GitHub ReadMe ซึ่งไม่รวมอยู่ใน HTML
import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
<!--rehype:ignore:start-->
Content ignored
<!--rehype:ignore:end-->
Some content is ignored, please check the source code
` ;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
rehypeRewrite = { ( node , index , parent ) => {
if ( node . tagName === "a" && parent && / ^h(1|2|3|4|5|6) / . test ( parent . tagName ) ) {
parent . children = parent . children . slice ( 1 )
}
} }
/>
) ;
} <!-- rehype:ignore:start --> Ignored content <!-- rehype:ignore:end --> Katex เป็นไลบรารี JavaScript ที่รวดเร็วและใช้งานง่ายสำหรับการแสดงผลทางคณิตศาสตร์ Tex บนเว็บเราทำการแสดงคณิตศาสตร์ผ่าน KaTeX
npm install katex import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
import { getCodeString } from 'rehype-rewrite' ;
import katex from 'katex' ;
import 'katex/dist/katex.css' ;
const source = `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 Demo ( ) {
const [ value , setValue ] = React . useState ( source ) ;
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
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 > ;
} ,
} }
/>
) ;
} การใช้นางเงือกเพื่อสร้างไดอะแกรมและผังงานจากข้อความในลักษณะเดียวกันกับ markdown
import React , { useState , useRef , useEffect , Fragment , useCallback } from "react" ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
import { getCodeString } from 'rehype-rewrite' ;
import mermaid from "mermaid" ;
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 = props . node && props . node . children ? getCodeString ( props . node . children ) : children [ 0 ] || '' ;
const reRender = async ( ) => {
if ( container && isMermaid ) {
try {
const str = await mermaid . render ( demoid . current , code ) ;
container . innerHTML = str . svg ;
} catch ( error ) {
container . innerHTML = error ;
}
}
}
useEffect ( ( ) => {
reRender ( )
} , [ 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 ref = { refElement } data-name = "mermaid" />
</ Fragment >
) ;
}
return < code > { children } </ code > ;
} ;
const source = `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 source = `
// ```mermaid
// graph TD;
// A-->B;
// A-->C;
// B-->D;
// C-->D;
// ```
// `;
export default function Demo ( ) {
return (
< MarkdownPreview
source = { source }
style = { { padding : 16 } }
components = { {
code : Code
} }
/>
) ;
} โปรดทราบว่า Markdown จะต้องถูกสุขลักษณะหากคุณไม่ไว้วางใจผู้เขียนของคุณอย่างสมบูรณ์ มิฉะนั้นแอปของคุณจะเสี่ยงต่อ XSS สิ่งนี้สามารถทำได้โดยการเพิ่ม rehype-sanitize เป็นปลั๊กอิน
import React from 'react' ;
import rehypeSanitize from "rehype-sanitize" ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `
## MarkdownPreview
**Hello world!!!** <IFRAME SRC="javascript:javascript:alert(window.origin);"></IFRAME>
<!-- test --> 123
<!-- test --> 456 <!-- test -->
` ;
const rehypePlugins = [ rehypeSanitize ] ;
export default function Demo ( ) {
return (
< MarkdownPreview source = { source } rehypePlugins = { rehypePlugins } style = { { padding : 16 } } />
)
} import { ReactMarkdownProps } from 'react-markdown' ;
import { RehypeRewriteOptions } from 'rehype-rewrite' ;
type MarkdownPreviewProps = {
prefixCls ?: string ;
className ?: string ;
source ?: string ;
disableCopy ?: boolean ;
style ?: React . CSSProperties ;
pluginsFilter ?: ( type : 'rehype' | 'remark' , plugin : PluggableList ) => PluggableList ;
wrapperElement ?: React . DetailedHTMLProps < React . HTMLAttributes < HTMLDivElement > , HTMLDivElement > & {
'data-color-mode' ?: 'light' | 'dark' ;
} ;
onScroll ?: ( e : React . UIEvent < HTMLDivElement > ) => void ;
onMouseOver ?: ( e : React . MouseEvent < HTMLDivElement > ) => void ;
rehypeRewrite ?: RehypeRewriteOptions [ 'rewrite' ] ;
} & ReactMarkdownProps ;source ( string , ค่าเริ่มต้น: '' )className ( string? )div ด้วยชื่อคลาสนี้ รายละเอียด ReactMarkdownProps นี้ อัพเกรด react-markdown V9
children ( string , ค่าเริ่มต้น: '' )className ( string? )div ด้วยชื่อคลาสนี้skipHtml ( boolean , ค่าเริ่มต้น:falsetrue )allowElement ( (element, index, parent) => boolean? , เป็นทางเลือก)allowedElements / disallowedElements ให้ใช้ก่อน!remarkPlugins ( Array.<Plugin> , ค่าเริ่มต้น: [] )rehypePlugins ( Array.<Plugin> , ค่าเริ่มต้น: [] )บันทึก
อัพเกรด react-markdown V8 ถึง V9
urlTransform transformImageUri และ transformLinkUri ถูกลบออก การมีสองฟังก์ชั่นนั้นค่อนข้างมากโดยเฉพาะอย่างยิ่งเนื่องจากมี URL มากขึ้นที่คุณอาจต้องการเปลี่ยน (หรืออาจไม่ปลอดภัยดังนั้น เรา จึงทำให้ปลอดภัย) และชื่อและ APIs ของพวกเขาค่อนข้างแปลก คุณสามารถใช้ prop urlTransform ใหม่แทนเพื่อเปลี่ยน URL ทั้งหมดของคุณ
linkTarget ตัวเลือก linkTarget ถูกลบออก คุณไม่ควรตั้งเป้าหมาย หากคุณต้องการให้ใช้ rehype-external-links
includeElementIndex ตัวเลือก includeElementIndex ถูกลบออกดังนั้น index จะไม่ถูกส่งผ่านไปยังส่วนประกอบ เขียนปลั๊กอินเพื่อส่ง index :
import { visit } from 'unist-util-visit'
function rehypePluginAddingIndex ( ) {
/**
* @param {import('hast').Root} tree
* @returns {undefined}
*/
return function ( tree ) {
visit ( tree , function ( node , index ) {
if ( node . type === 'element' && typeof index === 'number' ) {
node . properties . index = index
}
} )
}
}rawSourcePos ตัวเลือก rawSourcePos ถูกลบออกดังนั้น sourcePos จะไม่ถูกส่งผ่านไปยังส่วนประกอบ ส่วนประกอบทั้งหมดจะผ่าน node ดังนั้นคุณจะได้รับ node.position จากพวกเขา
sourcePos ตัวเลือก sourcePos ถูกลบออกดังนั้น data-sourcepos จะไม่ถูกส่งผ่านไปยังองค์ประกอบ เขียนปลั๊กอินเพื่อส่ง index :
import { stringifyPosition } from 'unist-util-stringify-position'
import { visit } from 'unist-util-visit'
function rehypePluginAddingIndex ( ) {
/**
* @param {import('hast').Root} tree
* @returns {undefined}
*/
return function ( tree ) {
visit ( tree , function ( node ) {
if ( node . type === 'element' ) {
node . properties . dataSourcepos = stringifyPosition ( node . position )
}
} )
}
}เมื่อเขียนทับส่วนประกอบอุปกรณ์ประกอบฉากเหล่านี้จะไม่ผ่านไปอีกต่อไป:
inline บน code - สร้างปลั๊กอินหรือใช้ pre สำหรับบล็อกlevel บน h1 , h2 , h3 , h4 , h5 , h6 - ตรวจสอบ node.tagName แทนchecked ใน li ตรวจสอบคลาส task-list-item หรือตรวจสอบ props.childrenindex เกี่ยวกับ li - สร้างปลั๊กอินordered ใน li - สร้างปลั๊กอินหรือตรวจสอบผู้ปกครองdepth ของ ol , ul - สร้างปลั๊กอินordered ซื้อ ol , ul - ตรวจสอบ node.tagName แทนisHeader on td , th - ตรวจสอบ node.tagName แทนisHeader on tr - สร้างปลั๊กอินหรือตรวจสอบเด็ก ๆ ใช้ความคิดเห็น 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; -->Here is a simple footnote [ ^ 1 ] . With some additional text after it.
[ ^ 1 ] : My reference. # Hello World
<!-- rehype:ignore:start --> Hello World <!-- rehype:ignore:end -->
Good!เอาท์พุท:
< h1 > Hello World </ h1 >
< p > Good! </ p > import React from 'react' ;
import MarkdownPreview from '@uiw/react-markdown-preview' ;
const source = `>
>
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
> [!WARNING]
> Urgent info that needs immediate user attention to avoid problems.
> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.
` ;
export default function Demo ( ) {
return (
< MarkdownPreview source = { source } style = { { padding : 16 } } />
)
} โดยค่าเริ่ม dark-mode จะถูกสลับโดยอัตโนมัติตามระบบ หากคุณต้องการสลับด้วยตนเองเพียงตั้งค่าพารามิเตอร์ data-color-mode="dark" สำหรับ Body
< html data-color-mode =" dark " > document . documentElement . setAttribute ( 'data-color-mode' , 'dark' )
document . documentElement . setAttribute ( 'data-color-mode' , 'light' ) สืบทอดตัวแปรสีที่กำหนดเองโดยการเพิ่ม .wmde-markdown-var SELECTOR
const Demo = ( ) => {
return (
< div >
< div className = "wmde-markdown-var" > </ div >
< MarkdownPreview source = "Hello World!" />
</ div >
)
} ตั้งค่าธีม light
<MarkdownPreview
source="Hello World!"
wrapperElement={{
+ "data-color-mode": "light"
}}
/>รันโครงการในโหมดการพัฒนา
# Step 1, run first,
# listen to the component compile and output the .js file
# listen for compilation output type .d.ts file
# listen to the component compile and output the .css file
npm run start
# Step 2, development mode, listen to compile preview website instance
npm run docสร้างแอพสำหรับการผลิตไปยังโฟลเดอร์ Build
npm run buildบิลด์มีขนาดเล็กและชื่อไฟล์รวมถึงแฮช แอพของคุณพร้อมที่จะนำไปใช้งานแล้ว!
หากคุณต้องการตัวแก้ไข Markdown ที่มีคุณสมบัติมากมายคุณสามารถใช้ @uiwjs/react-markdown-editor
เช่นเคยขอบคุณผู้มีส่วนร่วมที่น่าทึ่งของเรา!
ทำกับผู้ร่วมกระทำ
ได้รับใบอนุญาตภายใต้ใบอนุญาต MIT