forked from jsdf/react-native-htmlview
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhtmlToElement.js
More file actions
119 lines (102 loc) · 3.59 KB
/
Copy pathhtmlToElement.js
File metadata and controls
119 lines (102 loc) · 3.59 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
var React = require('react')
var ReactNative = require('react-native')
var htmlparser = require('./vendor/htmlparser2')
var entities = require('./vendor/entities')
var {
Text,
View
} = ReactNative
var LINE_BREAK = '\n';
var PARAGRAPH_BREAK = '\n';
var BULLET = '\u2022 ';
var inlineElements = ['a','span','em','font','label','b','strong','i','small'];
function htmlToElement(rawHtml, opts, done) {
function domToElement(dom, parent) {
if (!dom) return null
let domLen = dom.length;
let domTemp = {};
var getNodeData = function(node){
let nodeData = null;
if(node.children.length){
let nodeChild = node.children[0];
if(nodeChild && nodeChild.data){
nodeData = nodeChild.data;
}else{
nodeData = getNodeData(nodeChild);
}
}
return nodeData;
};
var renderInlineNode = function(index){
let thisIndex = index + 1;
if(thisIndex < domLen){
let nextNode = dom[thisIndex];
if(inlineElements.includes(nextNode.name)){
domTemp[thisIndex] = true;
let linkPressHandler = null;
if (nextNode.name == 'a' && nextNode.attribs && nextNode.attribs.href) {
linkPressHandler = () => opts.linkHandler(entities.decodeHTML(nextNode.attribs.href))
}
let nodeData = getNodeData(nextNode);
return (
<Text key={index} onPress={linkPressHandler} style={ opts.styles[nextNode.name]}>
{ entities.decodeHTML(nodeData) }
{ renderInlineNode(thisIndex)}
</Text>
)
}
if(nextNode.type == 'text'){
domTemp[thisIndex] = true;
return (
<Text style={ opts.styles['span'] } onPress={()=>null}>
{ entities.decodeHTML(nextNode.data) }
{ renderInlineNode(thisIndex)}
</Text>
)
}
}
return null;
};
return dom.map((node, index, list) => {
if(domTemp[index] === true){
return;
}
if (opts.customRenderer) {
let rendered = opts.customRenderer(node, index, list)
if (rendered || rendered === null) return rendered;
}
if (node.type == 'text' && node.data.trim()!='') {
let linkPressHandler = null;
if (parent && parent.name == 'a' && parent.attribs && parent.attribs.href) {
linkPressHandler = () => opts.linkHandler(entities.decodeHTML(parent.attribs.href))
}
return (
<Text key={index} onPress={linkPressHandler} style={parent ? opts.styles[parent.name] : null}>
{ parent && parent.name == 'pre'? LINE_BREAK : null }
{ parent && parent.name == "li"? BULLET : null }
{ parent && parent.name == 'br'? LINE_BREAK : null }
{ parent && parent.name == 'p' && index < list.length - 1 ? PARAGRAPH_BREAK : null }
{ parent && parent.name == 'h1' || parent && parent.name == 'h2' || parent && parent.name == 'h3' || parent && parent.name == 'h4' || parent && parent.name == 'h5'? PARAGRAPH_BREAK :null }
{ entities.decodeHTML(node.data) }
{ renderInlineNode(index) }
</Text>
)
}
if (node.type == 'tag') {
return (
<View key={ index }>
{ domToElement(node.children, node) }
</View>
)
}
})
}
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()
}
module.exports = htmlToElement