1- import React , { Fragment , useState } from 'react' ;
1+ import React , { Component , Fragment } from 'react' ;
22import MarkdownPreview from '@uiw/react-markdown-preview' ;
33// @ts -ignore
44import rehypeAttr from 'rehype-attr' ;
5- import { useEffect } from 'react' ;
65import Contributors from '../Contributors' ;
76import Footer from '../Footer' ;
87import styles from './index.module.less' ;
98
10- export interface MarkdownProps extends React . HTMLAttributes < HTMLDivElement > {
9+ interface MarkdownProps extends React . HTMLAttributes < HTMLDivElement > {
1110 path ?: string ;
1211 renderPage ?: ( ) => Promise < string > ;
1312}
1413
15- export default function Markdown ( props : MarkdownProps ) {
16- const { renderPage, path, style } = props ;
17- const [ mdStr , setMdStr ] = useState ( '' ) ;
18- const [ message , setMessage ] = useState ( '' ) ;
19- useEffect ( ( ) => {
20- if ( renderPage ) {
21- setMessage ( '' )
22- renderPage ( )
23- . then ( ( str ) => {
24- setMdStr ( str ) ;
25- } )
26- . catch ( ( ) => {
27- setMessage ( '页面加载失败!请刷新页面' )
28- } ) ;
14+ interface MarkdownState {
15+ markdown : string ;
16+ message ?: string ;
17+ }
18+
19+ // utilitary function to create a dictionary of packaged files
20+ // based on the output of require.context()
21+ // https://forum.ionicframework.com/t/react-app-loading-lots-of-markdown-html-fragments-with-images/188072/3
22+ export const importAll = ( r : any , cache : { [ key : string ] : string } ) => r . keys ( ) . forEach ( ( key : string ) => cache [ key ] = r ( key ) ) ;
23+ // const imageFiles: {[key: string]: string} = {};
24+ // importAll((require as any).context('../..', true, /\.(png|gif|jpg)$/), imageFiles);
25+
26+ export default class Markdown extends Component < MarkdownProps , MarkdownState > {
27+ path ?: string ;
28+ imageFiles : { [ key : string ] : string ; } = { } ;
29+ getMarkdown ?: ( ) => Promise < string > ;
30+ constructor ( props : MarkdownProps ) {
31+ super ( props ) ;
32+ this . state = {
33+ markdown : ''
34+ }
35+ if ( this . getMarkdown ) {
36+ this . getMarkdown = this . getMarkdown . bind ( this ) ;
37+ }
38+ }
39+ async componentDidMount ( ) {
40+ this . importAll ( ) ;
41+ this . setState ( { markdown : '' } ) ;
42+ if ( this . getMarkdown ) {
43+ try {
44+ const markdown = await this . getMarkdown ( ) ;
45+ this . setState ( { markdown } ) ;
46+ } catch ( error ) {
47+ this . setState ( { markdown : '页面加载失败!请刷新页面' } ) ;
48+ }
49+ }
50+ }
51+ importAll ( ) {
52+ importAll ( ( require as any ) . context ( '../..' , true , / \. ( p n g | g i f | j p g ) $ / ) , this . imageFiles ) ;
53+ }
54+ transformImageUri ( uri : string ) {
55+ if ( this . imageFiles [ uri ] ) {
56+ return ( this . imageFiles [ uri ] as any ) . default || this . imageFiles [ uri ]
57+ }
58+ return uri ;
59+ }
60+ render ( ) {
61+ const { style} = this . props ;
62+ if ( this . state . message ) {
63+ return (
64+ < div className = { styles . warpper } style = { style } >
65+ { this . state . message }
66+ < Contributors path = { this . path } />
67+ </ div >
68+ ) ;
2969 }
30- // eslint-disable-next-line react-hooks/exhaustive-deps
31- } , [ ] ) ;
32- if ( message ) {
3370 return (
34- < div className = { styles . warpper } style = { style } >
35- { message }
36- < Contributors path = { path } />
37- </ div >
71+ < Fragment >
72+ < div className = { styles . warpper } style = { style } >
73+ < MarkdownPreview
74+ source = { this . state . markdown }
75+ rehypePlugins = { [ [ rehypeAttr as any , { properties : 'attr' } ] ] }
76+ transformImageUri = { this . transformImageUri . bind ( this ) }
77+ components = { {
78+ /**
79+ * bgWhite 设置代码预览背景白色,否则为格子背景。
80+ * noCode 不显示代码编辑器。
81+ * noPreview 不显示代码预览效果。
82+ * noScroll 预览区域不显示滚动条。
83+ * codePen 显示 Codepen 按钮,要特别注意 包导入的问题,实例中的 import 主要用于 Codepen 使用。
84+ */
85+ code : ( {
86+ inline,
87+ node,
88+ noPreview,
89+ noScroll,
90+ bgWhite,
91+ noCode,
92+ codePen,
93+ codeSandbox,
94+ ...props
95+ } ) => {
96+ return < code { ...props } /> ;
97+ } ,
98+ } }
99+ />
100+ < Contributors path = { this . path } />
101+ </ div >
102+ < Footer placement = "left" />
103+ </ Fragment >
38104 ) ;
39105 }
40- return (
41- < Fragment >
42- < div className = { styles . warpper } style = { style } >
43- < MarkdownPreview
44- source = { mdStr }
45- // className={styles.markdown}
46- rehypePlugins = { [ [ rehypeAttr as any , { properties : 'attr' } ] ] }
47- components = { {
48- /**
49- * bgWhite 设置代码预览背景白色,否则为格子背景。
50- * noCode 不显示代码编辑器。
51- * noPreview 不显示代码预览效果。
52- * noScroll 预览区域不显示滚动条。
53- * codePen 显示 Codepen 按钮,要特别注意 包导入的问题,实例中的 import 主要用于 Codepen 使用。
54- */
55- code : ( {
56- inline,
57- node,
58- noPreview,
59- noScroll,
60- bgWhite,
61- noCode,
62- codePen,
63- codeSandbox,
64- ...props
65- } ) => {
66- return < code { ...props } /> ;
67- } ,
68- } }
69- />
70- < Contributors path = { path } />
71- </ div >
72- < Footer placement = "left" />
73- </ Fragment >
74- )
75106}
0 commit comments