@yozora/react-markdown
v3.0.0-alpha.15
Published
render markdown content in react
Downloads
109
Readme
This component is designed to render data of @yozora/ast.
Install
npm
npm install --save @yozora/react-markdown
yarn
yarn add @yozora/react-markdown @yozora/ast @yozora/ast-util
Usage
This component supports to preview all images in markdown documents with react-viewer. In order to be able to use react-viewer in React SSR, you will need the @loadable/component.
yarn add react-viewer @loadable/component
To use it with the following code snippet:
import loadable from '@loadable/component' import { ThemeSchema, ThemeProvider, createLightThemeStyle, createDarkenThemeStyle } from '@yozora/core-react-theme' import { Markdown, MarkdownProvider } from '@yozora/react-markdown' import React from 'react' const ImageViewer = loadable(() => import('react-viewer')) const ThemeStylesMap = { [ThemeSchema.LIGHT]: createLightThemeStyle(), [ThemeSchema.DARKEN]: createDarkenThemeStyle(), } function App() { const context = React.useMemo(() => ({ themeSchema: ThemeSchema.LIGHT, themeStyles: ThemeStylesMap[ThemeSchema.LIGHT], preference: { showCodeLineNo: true } }), []) return ( <ThemeProvider value={context}> <MarkdownProvider ImageViewer={ImageViewer}> <Markdown ast={ast} /> </MarkdownProvider> </ThemeProvider> ) }
In additional, if you want to render a markdown source contents from scratch, you will need the @yozora/parser to resolve the literal contents into mdast.
Then, you will need @yozora/ast-util to collect the link definition map and the footnote-definition map.
yarn add @yozora/parser @yozora/ast-util @yozora/ast
to integrated them with the following code snippet:
import { calcDefinitionMap, calcFootnoteDefinitionMap } from '@yozora/ast-util' import YozoraParser from '@yozora/parser' import { Markdown, MarkdownProvider } from '@yozora/react-markdown' const parser = new YozoraParser() const ast = parser.parse(`source markdown contents`, { shouldReservePosition: true }) const definitionMap = calcDefinitionMap(ast) const footnoteDefinitionMap = calcFootnoteDefinitionMap(ast) <MarkdownProvider definitionMap={definitionMap} footnoteDefinitionMap={footnoteDefinitionMap} > <Markdown ast={ast} /> </MarkdownProvider>
Render formula with mathjax.
import { Theme, ThemeProvider } from '@yozora/core-react-theme' import { MathJaxProvider, Markdown, MarkdownProvider } from '@yozora/react-markdown' <MathJaxProvider <ThemeProvider theme={Theme.LIGHT}> <MarkdownProvider> <Markdown ast={ast} /> </MarkdownProvider> </ThemeProvider> </MathJaxProvider>
Custom renderer map.
import React from 'react' import { Route } from 'react-route-dom' import { LinkReferenceType, LinkType } from '@yozora/ast' import { calcDefinitionMap, calcFootnoteDefinitionMap } from '@yozora/ast-util' import { NodeRendererContextType, NodesRenderer } from '@yozora/core-react-renderer' import { Theme, ThemeProvider } from '@yozora/core-react-theme' import YozoraParser from '@yozora/parser' import type { INodeRendererMap } from '@yozora/react-markdown' import { MathJaxProvider, Markdown, MarkdownProvider } from '@yozora/react-markdown' const sourceContents = `markdown contents` const parser = new YozoraParser() const ast = parser.parse(sourceContents, { shouldReservePosition: false }) const definitionMap = calcDefinitionMap(ast) const footnoteDefinitionMap = calcFootnoteDefinitionMap(ast) const customRendererMap: Partial<INodeRendererMap> = { [LinkType]: link => { const { url, title } = link return ( <InternalLink url={url} title={title}> <NodesRenderer nodes={link.children} /> </InternalLink> ) }, [LinkReferenceType]: (linkReference) => { return ( <NodeRendererContextType.Consumer> {({ definitionMap }) => { const definition = definitionMap[linkReference.identifier] const url: string = definition?.url ?? '' const title: string | undefined = definition?.title return ( <Route className="yozora-link" to={url} title={title} replace={true}> <NodesRenderer nodes={linkReference.children} /> </Route> ) }} </NodeRendererContextType.Consumer> ) }, } const wrapper = ( <MathJaxProvider mathjaxSrc="https://cdn.jsdelivr.net/npm/[email protected]/MathJax.js?config=TeX-MML-AM_CHTML"> <ThemeProvider theme={Theme.LIGHT}> <MarkdownProvider definitionMap={definitionMap} footnoteDefinitionMap={footnoteDefinitionMap} > <Markdown ast={ast} /> </MarkdownProvider> </ThemeProvider> </MathJaxProvider> )
Custom code renderer.
import type { CodeRunnerItem, CodeRunnerProps, CodeRunnerScope, } from '@yozora/react-code' import { MathRenderer } from '@yozora/react-markdown' import type { Engine } from 'd3-graphviz' import React from 'react' <YozoraMarkdownProvider definitionMap={definitionMap} footnoteDefinitionMap={footnoteDefinitionMap} codeRunners={codeRunners} > <YozoraMarkdown ast={ast} /> </YozoraMarkdownProvider> const codeRunners: CodeRunnerItem[] = [ { title: 'graphviz', pattern: /^graphviz|dot$/, runner: function GraphvizRunner( props: CodeRunnerProps, ): React.ReactElement { const { value, meta = {}, onError } = props return ( <GraphvizRenderer code={value} engine={meta.engine as Engine} onError={onError} /> ) }, }, { title: 'math', pattern: /^tex|latex|math|mathjax$/, runner: function MathJaxRunner( props: CodeRunnerProps, ): React.ReactElement { const value = props.value .replace(/^[\s\n]*([$]+)([\s\S]+)*\1[\s\n]*$/, '$2') .trim() return <MathRenderer value={value} /> }, }, ]
Don't need the footnote definitions:
import { Markdown, MarkdownProvider } from '@yozora/react-markdown' function Demo() { return ( <MarkdownProvider definitionMap={definitionMap}> <Markdown ast={ast} dontNeedFootnoteDefinitions={true} /> </MarkdownProvider> ) }
Props
YozoraMarkdownProvider
| Name | Type | Required | Default | Description | | :---------------------: | :---------------: | :------: | :-----: | :----------------------------------------------------------------------------------- | |
codeRunners
| See below |false
| - | Code runners, passed to @yozora/react-code-embed and @yozora/react-code-live | |darken
|boolean
|false
|false
| Enable the darken mode | |definitionMap
| See below |true
| - | Link / Image reference definitions | |footnoteDefinitionMap
| See below |true
| - | Footnote reference definitions | |customRendererMap
| See below |false
| - | @yozora/ast renderer map | |children
|React.ReactNode
|true
| - | Descendant elements. |YozoraMarkdown
| Name | Type | Required | Default | Description | | :---------------------------: | :-------------------: | :------: | :-----: | :---------------------------------------------------- | |
ast
| See below |true
| - | Root node of @yozora/ast | |className
|string
|false
| - | Root css class | |footnoteDefinitionsTitle
|React.ReactNode
|false
| - | Title of the footnote definitions | |dontNeedFootnoteDefinitions
|boolean
|false
| - | If true, then the footnote definitions wont be render | |style
|React.CSSProperties
|false
| - | Root css style |
Params
ast
:import type { Root } from '@yozora/ast' const ast: Root // Parse source contents into ast import YozoraParser from '@yozora/parser' const parser = new YozoraParser({ defaultParseOptions: { shouldReservePosition: false }, }) const ast = parser.parse(`source markdown contents`)
className
: The root element of this component will always bind with the CSS class'yozora-markdown'
.definitionMap
:import type { Definition } from '@yozora/ast' const definitionMap: Record<string, Definition> // Collect from ast import { calcDefinitionMap } from '@yozora/ast-util' const definitionMap = calcDefinitionMap(ast)
footnoteDefinitionMap
:import type { FootnoteDefinition } from '@yozora/ast' const footnoteDefinitionMap: Record<string, FootnoteDefinition> // Collect from ast import { calcFootnoteDefinitionMap } from '@yozora/ast-util' const definitionMap = calcFootnoteDefinitionMap(ast)
customRendererMap
:import type { INodeRendererMap } from '@yozora/react-markdown' const customRendererMap: Partial<INodeRendererMap>
ImageViewer
import loadable from '@loadable/component' const ImageViewer = loadable(() => import('react-viewer')
Overview
This component has some built-in sub-components for rendering data of @yozora/ast.
- @yozora/react-admonition
- [@yozora/react-inline-code][]
Related
- mdast
- @yozora/ast
- @yozora/tokenizer-admonition
- @yozora/tokenizer-autolink
- @yozora/tokenizer-autolink-extension
- @yozora/tokenizer-blockquote
- @yozora/tokenizer-break
- @yozora/tokenizer-definition
- @yozora/tokenizer-delete
- @yozora/tokenizer-emphasis
- @yozora/tokenizer-fenced-block
- @yozora/tokenizer-footnote
- @yozora/tokenizer-footnote-definition
- @yozora/tokenizer-footnote-reference
- @yozora/tokenizer-heading
- @yozora/tokenizer-image
- @yozora/tokenizer-image-reference
- @yozora/tokenizer-indented-block
- @yozora/tokenizer-inline-code
- @yozora/tokenizer-inline-math
- @yozora/tokenizer-link
- @yozora/tokenizer-link-reference
- @yozora/tokenizer-list
- @yozora/tokenizer-list-item
- @yozora/tokenizer-math
- @yozora/tokenizer-paragraph
- @yozora/tokenizer-setext-heading
- @yozora/tokenizer-table
- @yozora/tokenizer-text
- @yozora/tokenizer-thematic-break