Skip to content

Instantly share code, notes, and snippets.

@danieldunderfelt
Created July 10, 2019 05:49
Show Gist options
  • Save danieldunderfelt/1982786761cf4156b732b3a128a8050f to your computer and use it in GitHub Desktop.
Save danieldunderfelt/1982786761cf4156b732b3a128a8050f to your computer and use it in GitHub Desktop.
MDX in React-native
// The actual components that will be rendered with markdown. You may need to change or add components,
// this list is not fully tested. Some components may also never be used by MDX.
// Copied from https://github.com/mientjan/react-native-markdown-renderer and heavily modified.
import React from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import FitImage from 'react-native-fit-image'
import openUrl from './openUrl'
import { styles } from './styles'
const components = {
div: ({ children }) => <View style={styles.div}>{children}</View>,
wrapper: ({ children }) => <View style={styles.div}>{children}</View>,
textgroup: ({ children }) => {
return <Text style={styles.text}>{children}</Text>
},
inline: ({ children }) => {
return <Text>{children}</Text>
},
text: ({ children }) => {
return <Text>{children}</Text>
},
span: ({ children }) => {
return <Text>{children}</Text>
},
strong: ({ children }) => {
return <Text style={styles.strong}>{children}</Text>
},
a: ({ href, children }) => {
return (
<TouchableOpacity style={styles.link} onPress={() => openUrl(href)}>
{children}
</TouchableOpacity>
)
},
em: ({ children }) => {
return <Text style={styles.em}>{children}</Text>
},
h1: ({ children }) => {
return (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading1]}>
{children}
</Text>
</View>
)
},
h2: ({ children }) => {
return (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading2]}>
{children}
</Text>
</View>
)
},
h3: ({ children }) => (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading3]}>
{children}
</Text>
</View>
),
h4: ({ children }) => (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading4]}>
{children}
</Text>
</View>
),
h5: ({ children }) => (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading5]}>
{children}
</Text>
</View>
),
h6: ({ children }) => (
<View style={styles.headingContainer}>
<Text style={[styles.heading, styles.heading6]}>
{children}
</Text>
</View>
),
p: ({ children }) => <View style={styles.paragraph}>{children}</View>,
blockquote: ({ children }) => <View style={styles.blockquote}>{children}</View>,
inlineCode: ({ children }) => {
return <Text style={styles.codeInline}>{children}</Text>
},
code: ({ children }) => {
return <Text style={styles.codeBlock}>{children}</Text>
},
pre: ({ children }) => <View style={styles.pre}>{children}</View>,
ul: ({ children }) => {
return <View style={[styles.list, styles.listUnordered]}>{children}</View>
},
ol: ({ children }) => {
return <View style={[styles.list, styles.listOrdered]}>{children}</View>
},
li: ({ children }) => {
return (
<View style={styles.listUnorderedItem}>
<Text style={styles.listUnorderedItemIcon}>{'\u00B7'}</Text>
<View style={[styles.listItem]}>{children}</View>
</View>
)
},
table: ({ children }) => <View style={[styles.table]}>{children}</View>,
thead: ({ children }) => <View style={[styles.tableHeader]}>{children}</View>,
tbody: ({ children }) => <View>{children}</View>,
th: ({ children }) => {
return <View style={[styles.tableHeaderCell]}>{children}</View>
},
tr: ({ children }) => {
return <View style={[styles.tableRow]}>{children}</View>
},
td: ({ children }) => {
return <View style={[styles.tableRowCell]}>{children}</View>
},
hr: ({ children }) => {
return <View style={[styles.hr]} />
},
br: ({ children }) => <Text>{'\n'}</Text>,
img: ({ src, children }) => {
return <FitImage indicator={true} style={styles.image} source={{ uri: src }} />
},
}
export default components
// Use your MDX content with this component.
import React from 'react'
import MDX from '@mdx-js/runtime'
import components from '../utils/markdown/markdown'
// Renders a cimple loading spinner as a test
import Loading from './Loading'
const mdxComponents = {
...components,
Loading: Loading, // Add the custom component to the default markdown HTML components
}
// Add variables here if needed.
const scope = {}
// Children is an MDX string
const MdxContent = ({ children, style = {} }) => {
return (
<View style={style}>
<MDX components={mdxComponents} scope={scope}>
{children}
</MDX>
</View>
)
}
export default MdxContent
// To open URLs from Markdown links. Modify as needed. Untested.
// Copied from https://github.com/mientjan/react-native-markdown-renderer
import { Linking } from 'react-native';
export default function openUrl(url) {
if( url ) {
Linking.openURL(url);
}
}
// Add this to the root of your project.
// Adds Node libs that are needed, plus an fs implementation.
// mdx-runtime needs these.
// Yes, this works with Expo.
const libs = require('node-libs-react-native')
libs['fs'] = require.resolve('react-native-level-fs')
module.exports = {
resolver: {
extraNodeModules: libs,
},
}
// Styles used for the components. Change to your liking. Some styles may
// be superfluous or not working, this list is not tested.
// Copied from https://github.com/mientjan/react-native-markdown-renderer and modified slightly.
import { StyleSheet } from 'react-native'
export const styles = StyleSheet.create({
root: {},
view: {},
codeBlock: {
borderWidth: 1,
borderColor: '#CCCCCC',
backgroundColor: '#f5f5f5',
padding: 10,
borderRadius: 4,
},
codeInline: {
borderWidth: 1,
borderColor: '#CCCCCC',
backgroundColor: '#f5f5f5',
padding: 10,
borderRadius: 4,
},
del: {
backgroundColor: '#000000',
},
em: {
fontStyle: 'italic',
},
headingContainer: {
flexDirection: 'row',
},
heading: {},
heading1: {
fontSize: 32,
},
heading2: {
fontSize: 24,
},
heading3: {
fontSize: 18,
},
heading4: {
fontSize: 16,
},
heading5: {
fontSize: 13,
},
heading6: {
fontSize: 11,
},
hr: {
backgroundColor: '#000000',
height: 1,
},
blockquote: {
paddingHorizontal: 20,
paddingVertical: 10,
margin: 20,
backgroundColor: '#CCCCCC',
},
inlineCode: {
borderRadius: 3,
borderWidth: 1,
fontFamily: 'Courier',
fontWeight: 'bold',
},
list: {},
listItem: {
flex: 1,
flexWrap: 'wrap',
// backgroundColor: 'green',
},
listUnordered: {},
listUnorderedItem: {
flexDirection: 'row',
justifyContent: 'flex-start',
},
listUnorderedItemIcon: {
marginLeft: 10,
marginRight: 10,
lineHeight: 30,
},
listUnorderedItemText: {
fontSize: 20,
lineHeight: 20,
},
listOrdered: {},
listOrderedItem: {
flexDirection: 'row',
},
listOrderedItemIcon: {
marginLeft: 10,
marginRight: 10,
lineHeight: 30,
},
listOrderedItemText: {
fontWeight: 'bold',
lineHeight: 20,
},
div: {},
paragraph: {
marginTop: 10,
marginBottom: 10,
flexWrap: 'wrap',
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start',
},
hardbreak: {
width: '100%',
height: 1,
},
strong: {
fontWeight: 'bold',
},
table: {
borderWidth: 1,
borderColor: '#000000',
borderRadius: 3,
},
tableHeader: {},
tableHeaderCell: {
flex: 1,
// color: '#000000',
padding: 5,
// backgroundColor: 'green',
},
tableRow: {
borderBottomWidth: 1,
borderColor: '#000000',
flexDirection: 'row',
},
tableRowCell: {
flex: 1,
padding: 5,
},
text: {},
strikethrough: {
textDecorationLine: 'line-through',
},
pre: {},
link: {},
image: {
flex: 1,
},
})
@MaganAnkur
Copy link

Screen Shot 2021-10-07 at 10 07 09 PM

Any idea how to resolve this, I already installed mdx-js

@MaganAnkur
Copy link

I fixed above issue by upgrading @mdx-js/runtime to 2.0.0-next.9

@danieldunderfelt
Copy link
Author

@MaganAnkur Yes, that's what you needed to do. I've also made a library, check it out and give feedback: https://www.npmjs.com/package/rn-mdx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment