-
Notifications
You must be signed in to change notification settings - Fork 44
/
index.js
107 lines (98 loc) · 2.55 KB
/
index.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
105
106
107
var htmlparser = require("htmlparser2")
var converters = require('./converters/')
var escapeMap = {
"&": "&",
"<": "<",
">": ">",
""": "\"",
"'": "'",
"`": "`",
" ": " ",
" ": " "
}
var unescape = (function () {
var source = `(?:${Object.keys(escapeMap).join('|')})`
var testRegexp = RegExp(source)
var replaceRegexp = RegExp(source, 'g')
var escaper = function (match) {
return escapeMap[match]
}
return function (string) {
string = string || ''
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string
}
})()
/**
* @param html {String} the html to be onverted
* @param options {Object}
* {
* converter {String} which converter you choose
* overides {Object<String, Function>} override converter behavior, for example:
* {
* br: function (node) {
* return `\n\n` // let br tag break twice
* }
* }
* }
*/
module.exports = function (html, options) {
options = Object.assign({
converter: 'CommonMark'
}, options)
var converter = Object.assign(
Object.create(converters[options.converter]),
options.overides || {}
)
var nodeBuffer = []
var results = []
var isInPreNode = false
function convert(node) {
node.md = (node.md && node.md.join('')) || ''
return (converter[node.name] || converter['default'])(node) || ''
}
var parser = new htmlparser.Parser({
onopentag: function (name, attributes) {
var node = {
name: name,
attrs: attributes,
isInPreNode: isInPreNode
}
if (name === 'pre') {
isInPreNode = true
}
nodeBuffer.push(node)
},
ontext: function (text) {
if (/^\s+$/.test(text)) {
return
}
text = unescape(text)
var last = nodeBuffer[nodeBuffer.length - 1]
if (last) {
last.md = last.md || []
last.md.push(text)
} else {
results.push(text)
}
},
onclosetag: function (name) {
var last = nodeBuffer.pop()
var md = convert(last)
if (name === 'pre') {
isInPreNode = false
}
if (nodeBuffer.length === 0) {
return results.push(md)
}
var tail = nodeBuffer[nodeBuffer.length - 1]
tail.md = tail.md || []
tail.md.push(md)
}
}, {decodeEntities: false})
parser.write(html)
parser.end()
// remove the \n on head or tail
return typeof converter.cleanup == 'function'
? converter.cleanup(results.join(''))
: results.join('')
}