Skip to content

Instantly share code, notes, and snippets.

@nndnha
Forked from jsdf/ReactNativeHTML.js
Created September 28, 2016 05:40
Show Gist options
  • Save nndnha/94b989aaea86f26159e687b60e5a1af3 to your computer and use it in GitHub Desktop.
Save nndnha/94b989aaea86f26159e687b60e5a1af3 to your computer and use it in GitHub Desktop.

Revisions

  1. @jsdf jsdf revised this gist Mar 31, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion ReactNativeHTML.js
    Original file line number Diff line number Diff line change
    @@ -52,7 +52,7 @@ function domToElement(dom, parent) {
    })
    }

    var boldStyle = {fontWeight: '500'},
    var boldStyle = {fontWeight: '500'}
    var italicStyle = {fontStyle: 'italic'}
    var codeStyle = {fontFamily: 'Menlo'}

  2. @jsdf jsdf revised this gist Mar 31, 2015. 1 changed file with 54 additions and 27 deletions.
    81 changes: 54 additions & 27 deletions ReactNativeHTML.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,10 @@
    var React = require('react-native')
    var {View, Text} = React
    var {
    View,
    Text,
    LinkingIOS,
    StyleSheet,
    } = React

    // you might want to compile these two as standalone umd bundles
    // using `browserify --standalone` and `derequire`
    @@ -8,26 +13,6 @@ var {View, Text} = React
    var htmlparser = require('htmlparser2')
    var entities = require('entities')

    function domToElement(dom) {
    if (!dom) return <Text />

    return dom.map((node, index) => {
    if (node.type == 'text') {
    return <Text key={index}>{entities.decodeHTML(node.data)}</Text>
    }
    if (node.type == 'tag') {
    if (node.name == 'p') {
    return (
    <Text key={index}>{domToElement(node.children)}{'\n\n'}</Text>
    )
    }
    // TODO: implement i, b, pre
    // TODO: implement touch event on <a> tag
    return <Text key={index}>{domToElement(node.children)}</Text>
    }
    })
    }

    function htmlToElement(rawHtml, done) {
    var handler = new htmlparser.DomHandler(function (err, dom) {
    if (err) done(err)
    @@ -38,14 +23,56 @@ function htmlToElement(rawHtml, done) {
    parser.done()
    }

    var PARAGRAPH_BREAK = '\n\n'

    function domToElement(dom, parent) {
    if (!dom) return null

    return dom.map((node, index, list) => {
    if (node.type == 'text') {
    return (
    <Text key={index} style={parent ? styles[parent.name] : null}>
    {entities.decodeHTML(node.data)}
    </Text>
    )
    }
    if (node.type == 'tag') {
    var touchHandler = null
    if (node.name == 'a' && node.attribs && node.attribs.href) {
    touchHandler = () => LinkingIOS.openURL(entities.decodeHTML(node.attribs.href))
    }

    return (
    <Text key={index} onPress={touchHandler}>
    {domToElement(node.children, node)}
    {node.name == 'p' && index < list.length-1 ? PARAGRAPH_BREAK : null}
    </Text>
    )
    }
    })
    }

    var boldStyle = {fontWeight: '500'},
    var italicStyle = {fontStyle: 'italic'}
    var codeStyle = {fontFamily: 'Menlo'}

    var styles = StyleSheet.create({
    b: boldStyle,
    strong: boldStyle,
    i: italicStyle,
    em: italicStyle,
    pre: codeStyle,
    code: codeStyle,
    a: {
    fontWeight: '500',
    color: #007AFF,
    },
    })

    var HTML = React.createClass({
    mixins: [
    React.addons.PureRenderMixin,
    ],
    mixins: [React.addons.PureRenderMixin],
    getInitialState() {
    return {
    element: null,
    }
    return {element: null}
    },
    componentWillReceiveProps() {
    if (this.state.element) return
  3. @jsdf jsdf revised this gist Mar 31, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion ReactNativeHTML.js
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,7 @@ function domToElement(dom) {
    // TODO: implement touch event on <a> tag
    return <Text key={index}>{domToElement(node.children)}</Text>
    }
    })
    })
    }

    function htmlToElement(rawHtml, done) {
  4. @jsdf jsdf revised this gist Mar 31, 2015. 1 changed file with 7 additions and 3 deletions.
    10 changes: 7 additions & 3 deletions ReactNativeHTML.js
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,13 @@
    var _ = require('underscore')
    var htmlparser = require('../vendor/htmlparser2')
    var entities = require('../vendor/entities')
    var React = require('react-native')
    var {View, Text} = React

    // you might want to compile these two as standalone umd bundles
    // using `browserify --standalone` and `derequire`
    // until this issue is fixed: https://github.com/facebook/react-native/issues/231
    // and then just require the umd bundle files directly
    var htmlparser = require('htmlparser2')
    var entities = require('entities')

    function domToElement(dom) {
    if (!dom) return <Text />

  5. @jsdf jsdf created this gist Mar 31, 2015.
    74 changes: 74 additions & 0 deletions ReactNativeHTML.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    var _ = require('underscore')
    var htmlparser = require('../vendor/htmlparser2')
    var entities = require('../vendor/entities')
    var React = require('react-native')
    var {View, Text} = React

    function domToElement(dom) {
    if (!dom) return <Text />

    return dom.map((node, index) => {
    if (node.type == 'text') {
    return <Text key={index}>{entities.decodeHTML(node.data)}</Text>
    }
    if (node.type == 'tag') {
    if (node.name == 'p') {
    return (
    <Text key={index}>{domToElement(node.children)}{'\n\n'}</Text>
    )
    }
    // TODO: implement i, b, pre
    // TODO: implement touch event on <a> tag
    return <Text key={index}>{domToElement(node.children)}</Text>
    }
    })
    }

    function htmlToElement(rawHtml, done) {
    var handler = new htmlparser.DomHandler(function (err, dom) {
    if (err) done(err)
    done(null, domToElement(dom))
    })
    var parser = new htmlparser.Parser(handler)
    parser.write(rawHtml)
    parser.done()
    }

    var HTML = React.createClass({
    mixins: [
    React.addons.PureRenderMixin,
    ],
    getInitialState() {
    return {
    element: null,
    }
    },
    componentWillReceiveProps() {
    if (this.state.element) return
    this.startHtmlRender()
    },
    componentDidMount() {
    this.startHtmlRender()
    },
    startHtmlRender() {
    if (!this.props.value) return
    if (this.renderingHtml) return

    this.renderingHtml = true
    htmlToElement(this.props.value, (err, element) => {
    this.renderingHtml = false

    if (err) return console.error(err)

    if (this.isMounted()) this.setState({element})
    })
    },
    render() {
    if (this.state.element) {
    return <Text children={this.state.element} />
    }
    return <Text />
    }
    })

    module.exports = HTML