This repository has been archived by the owner on Mar 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 96
/
HTML.js
104 lines (93 loc) · 3.45 KB
/
HTML.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import React from 'react'
import { View } from 'react-native'
import shallowCompare from 'react-addons-shallow-compare'
import htmlparser2 from 'htmlparser2'
import HTMLElement from './HTMLElement'
import HTMLTextNode from './HTMLTextNode'
import HTMLRenderers from './HTMLRenderers'
import HTMLStyles from './HTMLStyles'
class HTML extends React.Component {
/* ****************************************************************************/
// Class
/* ****************************************************************************/
static propTypes = {
html: React.PropTypes.string.isRequired,
htmlStyles: React.PropTypes.object,
onLinkPress: React.PropTypes.func,
renderers: React.PropTypes.object.isRequired
}
static defaultProps = {
renderers: HTMLRenderers
}
/* ****************************************************************************/
// Data Lifecycle
/* ****************************************************************************/
shouldComponentUpdate (nextProps, nextState) {
return shallowCompare(this, nextProps, nextState)
}
/* ****************************************************************************/
// Rendering
/* ****************************************************************************/
/**
* Converts the html elements to RN elements
* @param htmlElements: the array of html elements
* @param parentTagName='body': the parent html element if any
* @param parentIsText: true if the parent element was a text-y element
* @return the equivalent RN elements
*/
renderHtmlAsRN (htmlElements, parentTagName, parentIsText) {
return htmlElements
.map((node, index, list) => {
if (node.type === 'text') {
const str = HTMLTextNode.removeWhitespaceListHTML(node.data, index, parentTagName)
if (str.length) {
return (<HTMLTextNode key={index}>{str}</HTMLTextNode>)
} else {
return undefined
}
} else if (node.type === 'tag') {
// Generate grouping info if we are a group-type element
let groupInfo
if (node.name === 'li') {
groupInfo = {
index: htmlElements.reduce((acc, e) => {
if (e === node) {
acc.found = true
} else if (!acc.found && e.type === 'tag' && e.name === 'li') {
acc.index++
}
return acc
}, {index: 0, found: false}).index,
count: htmlElements.filter((e) => e.type === 'tag' && e.name === 'li').length
}
}
return (
<HTMLElement
key={index}
htmlStyles={this.props.htmlStyles}
htmlAttribs={node.attribs}
tagName={node.name}
groupInfo={groupInfo}
parentTagName={parentTagName}
parentIsText={parentIsText}
onLinkPress={this.props.onLinkPress}
renderers={this.props.renderers}>
{this.renderHtmlAsRN(node.children, node.name, !HTMLStyles.blockElements.has(node.name))}
</HTMLElement>)
}
})
.filter((e) => e !== undefined)
}
render () {
let rnNodes
const parser = new htmlparser2.Parser(
new htmlparser2.DomHandler((_err, dom) => {
rnNodes = this.renderHtmlAsRN(dom, 'body', false)
})
)
parser.write(this.props.html)
parser.done()
return (<View>{rnNodes}</View>)
}
}
module.exports = HTML