react-native-markdown-display

repository·master·Indexed 21 days ago

https://github.com/iamacup/react-native-markdown-display

A CommonMark compatible Markdown renderer for React Native that uses native components instead of a WebView. It supports CommonMark spec, syntax extensions like URL autolinking and typographer, and allows deep customization of styles and rendering rules for each markdown element. Version 7.0.2. Note: This library is no longer actively maintained; migration to react-native-enriched-markdown is recommended.

Tokens
7.3K
Snippets
19
Records
23
Agent score
71%

What's inside react-native-markdown-display

  1. Customize rendering with the rules prop

    master

    The rules prop allows you to define custom render functions for specific Markdown elements. Each rule is a function that receives (node, children, parent, styles) and should return a React element. This is useful for injecting custom logic or unique UI components into the Markdown tree.

    Example of overriding headings:

    const rules = {
        heading1: (node, children, parent, styles) =>
          <Text key={node.key} style={[styles.heading, styles.heading1]}>
            >> H1 TEXT HERE >> "{children}"
          </Text>,
    };
    
    <Markdown rules={rules}>
      {copy}
    </Markdown>
  2. Get Started with react-native-markdown-display

    master

    To use the library, import the Markdown component and pass your markdown string as children. The renderer uses native components rather than a WebView, allowing for native styling and performance.

    import React from 'react';
    import { SafeAreaView, ScrollView, StatusBar } from 'react-native';
    import Markdown from 'react-native-markdown-display';
    
    const copy = `# h1 Heading 8-) 
    
    **This is some bold text!**
    
    This is normal text
    `;
    
    const App = () => {
      return (
        <>
          <StatusBar barStyle="dark-content" />
          <SafeAreaView>
            <ScrollView
              contentInsetAdjustmentBehavior="automatic"
              style={{height: '100%'}}
            >
              <Markdown>
                {copy}
              </Markdown>
            </ScrollView>
          </SafeAreaView>
        </>
      );
    };
    
    export default App;
    import React from 'react';
    import { SafeAreaView, ScrollView, StatusBar } from 'react-native';
    
    import Markdown from 'react-native-markdown-display';
    
    const copy = `# h1 Heading 8-) 
    
    **This is some bold text!**
    
    This is normal text
    `;
    
    const App: () => React$Node = () => {
      return (
        <>
          <StatusBar barStyle="dark-content" />
          <SafeAreaView>
            <ScrollView
              contentInsetAdjustmentBehavior="automatic"
              style={{height: '100%'}}
            >
              <Markdown>
                {copy}
              </Markdown>
            </ScrollView>
          </SafeAreaView>
        </>
      );
    };
    
    export default App;
  3. Debug Markdown parsing with AST and HTML output

    master

    If you need to inspect how the markdown is being processed, you can use the MarkdownIt instance directly to generate the Abstract Syntax Tree (AST) or the raw HTML string. This is useful for understanding the structure of the node objects passed to custom render rules.

    • markdownItInstance.parse(content, options): Returns an array of Token objects representing the AST.
    • markdownItInstance.render(content): Returns the generated HTML string.
    import Markdown, { MarkdownIt } from 'react-native-markdown-display';
    import blockEmbedPlugin from 'markdown-it-block-embed';
    
    const markdownItInstance = 
        MarkdownIt({typographer: true})
          .use(blockEmbedPlugin, {
            containerClassName: "video-embed"
          });
    
    const copy = `
    # Some header
    
    @[youtube](lJIrF4YjHfQ)
    `;
    
    // Inspect the AST tree used by the component
    const astTree = markdownItInstance.parse(copy, {});
    console.log(astTree);
    
    // Inspect the generated HTML (for reference)
    const html = markdownItInstance.render(copy);
    console.log(html);
  4. Pre-process Markdown using AST

    master

    If you need to process Markdown data outside the component, you can convert a string into an Abstract Syntax Tree (AST) using stringToTokens and tokensToAST. You can then pass this AST directly as the children of the Markdown component.

    import Markdown, { MarkdownIt, tokensToAST, stringToTokens } from 'react-native-markdown-display';
    
    const markdownItInstance = MarkdownIt({typographer: true});
    const ast = tokensToAST(stringToTokens(copy, markdownItInstance));
    
    <Markdown>
      {ast}
    </Markdown>
  5. Migrate to react-native-enriched-markdown

    master

    ⚠️ Note: react-native-markdown-display is no longer actively maintained.

    It is highly recommended to migrate to react-native-enriched-markdown. This is a high-performance, fully native Markdown renderer built with Fabric (New Architecture) that uses md4c for fast, standards-compliant parsing. It supports CommonMark, GFM, native text selection, accessibility, and RTL support.

    To install the recommended replacement:

    yarn add react-native-enriched-markdown
    yarn add react-native-enriched-markdown
  6. Style Markdown elements using the style prop

    master

    You can apply styles to Markdown elements using a style object passed to the Markdown component. The styling system works similarly to CSS: styles applied to the body key act as global defaults for the entire document and can be overridden by more specific element styles (e.g., heading1).

    Important Note on 'text' styling: The text rule is not applied to all rendered text (for example, it does not apply to list bullet points). To color all text in the document, apply the color to the body style instead.

    <Markdown
      style={{
        body: {color: 'red', fontSize: 10},
        heading1: {color: 'purple'},
        code_block: {color: 'black', fontSize: 14}
      }}
    >
      {copy}
    </Markdown>
  7. Disable specific Markdown types

    master

    You can disable specific Markdown features (like images or links) by passing a configured markdownit instance to the Markdown component. The library exports MarkdownIt so you can configure it without adding it as a direct dependency.

    import Markdown, { MarkdownIt } from 'react-native-markdown-display';
    
    <Markdown
      markdownit={MarkdownIt({typographer: true}).disable([ 'link', 'image' ])}
    >
      {copy}
    </Markdown>
  8. Extend Markdown support with Plugins and Render Rules

    master

    You can add extra syntax support by integrating markdown-it compatible plugins. This is a two-step process:

    1. Integrate the Plugin

    Create a MarkdownIt instance using the MarkdownIt function provided by the library. Use .use(plugin, options) to attach your plugin. Pass this instance to the markdownit prop of the Markdown component.

    Tip: Use the debugPrintTree prop on the Markdown component to see the rendered tree in your console. This helps identify the name of the new rule (e.g., video) that the plugin introduced.

    2. Implement Render Rules and Styles

    Once you know the rule name (e.g., video), provide a corresponding function in the rules prop of the Markdown component. This function receives (node, children, parent, styles) and should return a React component. You can also define custom styles for this new rule in the style prop.

    Note: The node object contains all necessary metadata (like sourceInfo, type, attributes) required to render the custom component correctly.

    import React from 'react';
    import { SafeAreaView, ScrollView, Text } from 'react-native';
    import Markdown, { MarkdownIt } from 'react-native-markdown-display';
    import blockEmbedPlugin from 'markdown-it-block-embed';
    
    // 1. Setup the markdown-it instance with the plugin
    const markdownItInstance = 
        MarkdownIt({typographer: true})
          .use(blockEmbedPlugin, {
            containerClassName: "video-embed"
          });
    
    const copy = `
    # Some header
    
    @[youtube](lJIrF4YjHfQ)
    `;
    
    const App = () => {
      return (
        <SafeAreaView>
          <ScrollView>
            <Markdown
              markdownit={markdownItInstance}
              style={{
                video: {
                  color: 'red',
                }
              }}
              rules={{
                // 2. Define the render rule for the new 'video' type
                video: (node, children, parent, styles) => {
                  // node contains metadata like sourceInfo.videoID
                  return (
                    <Text key={node.key} style={styles.video}>
                      Return a video component instead of this text component!
                    </Text>
                  );
                }
              }}
            >
              {copy}
            </Markdown>
          </ScrollView>
        </SafeAreaView>
      );
    };
    
    export default App;
  9. Handle link presses with onLinkPress

    master

    By default, links use React Native's Linking.openURL. You can intercept link clicks using the onLinkPress callback.

    • Return true to allow the default Linking.openURL behavior.
    • Return false to handle the link press yourself (e.g., for custom navigation or logic).
    const onLinkPress = (url) => {
        if (url) {
          // custom logic here
          return false;
        }
        return true;
      }
    
    <Markdown onLinkPress={onLinkPress}>
      {copy}
    </Markdown>
  10. Common Props for the Markdown component

    master

    The <Markdown> component accepts several props to control rendering, styling, and behavior:

    PropertyDefaultRequiredDescription
    childrenN/AtrueThe markdown string to render, or the pre-processed tree
    stylesourcefalseAn object to override the styling for the various rules
    mergeStyletruefalseIf true, when a style is supplied, the individual items are merged with the default styles instead of overwriting them
    rulessourcefalseAn object of rules that specify how to render each markdown item
    onLinkPressimport { Linking } from 'react-native'; and Linking.openURL(url);falseA handler function to change click behaviour
    debugPrintTreefalsefalseWill print the AST tree to the console to help you see what the markdown is being translated to
  11. Advanced Props for the Markdown component

    master

    These additional options provide deeper control over the rendering engine and image handling:

    PropertyDefaultRequiredDescription
    rendererinstanceOf(AstRenderer)falseUsed to specify a custom renderer. Note: you cannot use rules or style props when using a custom renderer
    markdownitinstanceOf(MarkdownIt)falseA custom markdownit instance with your configuration. Default is MarkdownIt({typographer: true})
    maxTopLevelChildrennullfalseIf defined as a number, will only render out the first n top level children, then will try to render out topLevelMaxExceededItem
    topLevelMaxExceededItem<Text key="dotdotdot">...</Text>falseThe component rendered when maxTopLevelChildren is hit. Ensure this has a unique key
    allowedImageHandlers['data:image/png;base64', 'data:image/gif;base64', 'data:image/jpeg;base64', 'https://', 'http://']falseAny image that does not start with one of these will have the defaultImageHandler value prepended to it (unless defaultImageHandler is null)
    defaultImageHandlerhttp://falseA prefix prepended to an image URL if it does not start with something in the allowedImageHandlers array. If set to null, the image won't be rendered