@yozora/react-markdown
TypeScript icon, indicating that this package has built-in type declarations

3.0.0-alpha.15 • Public • Published

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/mathjax@2.7.5/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.

Related

Package Sidebar

Install

npm i @yozora/react-markdown

Weekly Downloads

2

Version

3.0.0-alpha.15

License

MIT

Unpacked Size

108 kB

Total Files

8

Last publish

Collaborators

  • lemonclown