React Component Preview Text في متصفح الويب. الحد الأدنى من CSS لتكرار نمط تخفيض github. يتم تحويل موقع المستند الحالي باستخدام مكون React هذا.
@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 لا يحتوي مكون رمز إعادة تسليط الضوء على الرمز 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 Math على الويب ، ونحن نقوم بإعداد الرياضيات من خلال 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 > ;
} ,
} }
/>
) ;
} باستخدام حورية البحر إلى توليد المخطط ومخطط انسيابي من النص بطريقة مماثلة مثل التخفيض
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 التي قد ترغب في تغييرها (أو والتي قد تكون غير آمنة لذلك نجعلها آمنة). وكان اسمهم وواجهة برمجة التطبيقات غريبة بعض الشيء. يمكنك استخدام دعامة 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 على td ، th - تحقق من node.tagName بدلاً من ذلكisHeader على tr - قم بإنشاء مكون إضافي أو تحقق من الأطفال استخدم تعليقات 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; -->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" للجسم.
< html data-color-mode =" dark " > document . documentElement . setAttribute ( 'data-color-mode' , 'dark' )
document . documentElement . setAttribute ( 'data-color-mode' , 'light' ) ورث متغيرات اللون المخصص عن طريق إضافة محدد .wmde-markdown-var .
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يبني التطبيق للإنتاج إلى مجلد البناء.
npm run buildتم تصنيع البناء ويتضمن أسماء الملفات التجزئة. تطبيقك جاهز للنشر!
إذا كنت بحاجة إلى مزيد من المحرر الغني بالميزات ، فيمكنك استخدام @uiwjs/react-markdown-editor
كما هو الحال دائمًا ، بفضل مساهمينا المذهلين!
مصنوعة مع موظفي العمل.
مرخصة بموجب ترخيص معهد ماساتشوستس للتكنولوجيا.