diff options
Diffstat (limited to 'plugins/base/src/main/kotlin/parsers/HtmlParser.kt')
-rw-r--r-- | plugins/base/src/main/kotlin/parsers/HtmlParser.kt | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/plugins/base/src/main/kotlin/parsers/HtmlParser.kt b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt new file mode 100644 index 00000000..ece3cf24 --- /dev/null +++ b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt @@ -0,0 +1,89 @@ +package org.jetbrains.dokka.base.parsers + +import org.jetbrains.dokka.model.doc.* +import org.jetbrains.dokka.base.parsers.factories.DocTagsFromStringFactory +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) { + DocTagsFromStringFactory.getInstance(nodeName, nodesCache.getOrDefault(currentDepth, mutableListOf()).toList(), params, body).also { + nodesCache[currentDepth] = mutableListOf() + currentDepth = depth + } + } else { + DocTagsFromStringFactory.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) +} + + |