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
|
package org.jetbrains.dokka.parsers
import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.parsers.factories.DocNodesFromStringFactory
import org.jsoup.Jsoup
import org.jsoup.nodes.Node
import org.jsoup.select.NodeFilter
import org.jsoup.select.NodeTraversor
class HtmlParser : Parser() {
inner class NodeFilterImpl : NodeFilter {
private val nodesCache: MutableMap<Int, MutableList<DocTag>> = mutableMapOf()
private var currentDepth = 0
fun collect(): DocTag = nodesCache[currentDepth]!![0]
override fun tail(node: Node?, depth: Int): NodeFilter.FilterResult {
val nodeName = node!!.nodeName()
val nodeAttributes = node.attributes()
if(nodeName in listOf("#document", "html", "head"))
return NodeFilter.FilterResult.CONTINUE
val body: String
val params: Map<String, String>
if(nodeName != "#text") {
body = ""
params = nodeAttributes.map { it.key to it.value }.toMap()
} else {
body = nodeAttributes["#text"]
params = emptyMap()
}
val docNode = if(depth < currentDepth) {
DocNodesFromStringFactory.getInstance(nodeName, nodesCache.getOrDefault(currentDepth, mutableListOf()).toList(), params, body).also {
nodesCache[currentDepth] = mutableListOf()
currentDepth = depth
}
} else {
DocNodesFromStringFactory.getInstance(nodeName, emptyList(), params, body)
}
nodesCache.getOrDefault(depth, mutableListOf()) += docNode
return NodeFilter.FilterResult.CONTINUE
}
override fun head(node: Node?, depth: Int): NodeFilter.FilterResult {
val nodeName = node!!.nodeName()
if(currentDepth < depth) {
currentDepth = depth
nodesCache[currentDepth] = mutableListOf()
}
if(nodeName in listOf("#document", "html", "head"))
return NodeFilter.FilterResult.CONTINUE
return NodeFilter.FilterResult.CONTINUE
}
}
private fun htmlToDocNode(string: String): DocTag {
val document = Jsoup.parse(string)
val nodeFilterImpl = NodeFilterImpl()
NodeTraversor.filter(nodeFilterImpl, document.root())
return nodeFilterImpl.collect()
}
private fun replaceLinksWithHrefs(javadoc: String): String = Regex("\\{@link .*?}").replace(javadoc) {
val split = it.value.dropLast(1).split(" ")
if(split.size !in listOf(2, 3))
return@replace it.value
if(split.size == 3)
return@replace "<documentationlink href=\"${split[1]}\">${split[2]}</documentationlink>"
else
return@replace "<documentationlink href=\"${split[1]}\">${split[1]}</documentationlink>"
}
override fun parseStringToDocNode(extractedString: String) = htmlToDocNode(extractedString)
override fun preparse(text: String) = replaceLinksWithHrefs(text)
}
|