Created
October 2, 2018 10:50
-
-
Save yleflour/0f76a0b793e6c5516bb404d035a8326c to your computer and use it in GitHub Desktop.
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
import React from 'react'; | |
import { Image, Text, View } from 'react-native'; | |
function renderImage(node: any, output: any, state: any, styles: any) { | |
const { imageWrapper: wrapperStyle, image: imageStyle } = styles; | |
/** | |
* Prevent Native crash (View in Text) from occuring | |
*/ | |
if (state.inline) { | |
// @TODO send a sentry bug report | |
console.warn('Trying to insert an image within text'); | |
return null; | |
} | |
return ( | |
<View | |
key={state.key} | |
style={ | |
node.width || node.height | |
? [wrapperStyle, paddedSize(node, wrapperStyle)] | |
: wrapperStyle | |
} | |
> | |
<Image source={{ uri: node.target }} style={imageStyle} /> | |
</View> | |
); | |
} | |
function paragraphRenderer() { | |
const renderText = textContentRenderer('paragraph'); | |
return (node: any, output: any, state: any, styles: any) => { | |
if ( | |
node.content instanceof Array && | |
node.content.length === 1 && | |
node.content[0].type === 'image' | |
) { | |
const imageNode = node.content[0]; | |
return renderImage(imageNode, output, state, styles); | |
} else { | |
return renderText(node, output, state, styles); | |
} | |
}; | |
} | |
function textContentRenderer(styleName: any, styleName2?: any) { | |
return (node: any, output: any, state: any, styles: any) => ( | |
<Text | |
key={state.key} | |
style={ | |
styleName2 ? [styles[styleName], styles[styleName2]] : styles[styleName] | |
} | |
> | |
{typeof node.content === 'string' | |
? node.content | |
: output(node.content, { ...state, inline: true })} | |
</Text> | |
); | |
} | |
function paddedSize(size: any, style: any) { | |
function either(a: any, b: any) { | |
return a === undefined ? b : a; | |
} | |
const { | |
padding = 0, | |
paddingLeft, | |
paddingRight, | |
paddingTop, | |
paddingBottom, | |
} = style; | |
return { | |
width: | |
size.width + either(paddingLeft, padding) + either(paddingRight, padding), | |
height: | |
size.height + | |
either(paddingTop, padding) + | |
either(paddingBottom, padding), | |
}; | |
} | |
function renderListBullet(index: any, node: any, styles: any) { | |
return node.ordered ? ( | |
<Text style={styles.listItemNumber}>{`${index + 1}.`}</Text> | |
) : ( | |
<Text style={styles.listItemBullet}> | |
{styles.listItemBullet && styles.listItemBullet.content | |
? styles.listItemBullet.content | |
: '\u2022'} | |
</Text> | |
); | |
} | |
export const markdownRenderers = Object.freeze({ | |
blockQuote: textContentRenderer('blockQuote'), | |
br: (node: any, output: any, state: any, styles: any) => ( | |
<Text key={state.key} style={styles.br}> | |
{'\n\n'} | |
</Text> | |
), | |
codeBlock: textContentRenderer('codeBlock'), | |
del: textContentRenderer('del'), | |
em: textContentRenderer('em'), | |
heading: (node: any, output: any, state: any, styles: any) => | |
textContentRenderer('heading', 'heading' + node.level)( | |
node, | |
output, | |
state, | |
styles | |
), | |
hr: (node: any, output: any, state: any, styles: any) => ( | |
<View key={state.key} style={styles.hr} /> | |
), | |
image: renderImage, | |
inlineCode: textContentRenderer('inlineCode'), | |
link: (node: any, output: any, state: any, styles: any) => { | |
const onPress = state.onLinkPress; | |
return ( | |
<Text | |
key={state.key} | |
style={styles.link} | |
onPress={onPress ? () => onPress(node.target) : () => null} | |
> | |
{typeof node.content === 'string' | |
? node.content | |
: output(node.content, { ...state, inline: true })} | |
</Text> | |
); | |
}, | |
list: (node: any, output: any, state: any, styles: any) => { | |
/** | |
* Prevent View in Text crash by checking if the render tree is | |
* already in a Text (inline) node | |
*/ | |
if (state.inline) { | |
// @TODO send a sentry bug report | |
console.warn('Trying to insert a list within text'); | |
return ( | |
<Text> | |
{node.items.map((item: any, i: number) => ( | |
<Text key={i}> | |
{renderListBullet(i, node, styles)} | |
<Text | |
style={ | |
node.ordered | |
? styles.listItemOrderedContent | |
: styles.listItemUnorderedContent | |
} | |
> | |
{output(item, { ...state, inline: true })} | |
</Text> | |
</Text> | |
))} | |
</Text> | |
); | |
} | |
/** | |
* Render the list at root level | |
*/ | |
return ( | |
<View key={state.key} style={styles.list}> | |
{node.items.map((item: any, i: number) => ( | |
<View key={i} style={styles.listItem}> | |
{renderListBullet(i, node, styles)} | |
<Text | |
style={ | |
node.ordered | |
? styles.listItemOrderedContent | |
: styles.listItemUnorderedContent | |
} | |
> | |
{output(item, { ...state, inline: true })} | |
</Text> | |
</View> | |
))} | |
</View> | |
); | |
}, | |
newline: (node: any, output: any, state: any, styles: any) => ( | |
<Text key={state.key} style={styles.newline}> | |
{'\n'} | |
</Text> | |
), | |
paragraph: paragraphRenderer(), | |
strong: textContentRenderer('strong'), | |
text: textContentRenderer('text'), | |
u: textContentRenderer('u'), | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment