Created
July 10, 2019 05:49
-
-
Save danieldunderfelt/1982786761cf4156b732b3a128a8050f to your computer and use it in GitHub Desktop.
MDX in React-native
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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, | |
}, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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, | |
}, | |
}) |
@slorber that would be ideal! I will continue developing an MDX solution for my needs soon. I'm also looking at https://github.com/kentcdodds/mdx-bundler, it might be useful.
Didn't work on this much this year but my talk on MDX + RN is here: https://www.youtube.com/watch?v=ScgFQojbAAc
The 2nd part is dedicated to running MDX in RN
Didn't work on this much this year but my talk on MDX + RN is here: https://www.youtube.com/watch?v=ScgFQojbAAc
The 2nd part is dedicated to running MDX in RN
Great, thanks! I'll check it out.
I fixed above issue by upgrading @mdx-js/runtime to 2.0.0-next.9
@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
@andrekovac I have been thinking about it! The app where this is used has been on ice for a while, but I'm continuing with it soon and I want to develop a great way to handle content within it. So yeah, something will probably come of this yet!