package org.jetbrains.dokka.base.renderers.html
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.html.*
import kotlinx.html.stream.createHTML
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.renderers.DefaultRenderer
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
import org.jetbrains.dokka.plugability.query
import java.io.File
import java.net.URI
open class HtmlRenderer(
context: DokkaContext
) : DefaultRenderer(context) {
private val sourceSetDependencyMap = context.configuration.sourceSets.map { sourceSet ->
sourceSet to context.configuration.sourceSets.filter { sourceSet.dependentSourceSets.contains(it.sourceSetID) }
}.toMap()
private val pageList = mutableMapOf>()
override val preprocessors = context.plugin().query { htmlPreprocessors }
override fun FlowContent.wrapGroup(
node: ContentGroup,
pageContext: ContentPage,
childrenCallback: FlowContent.() -> Unit
) {
val additionalClasses = node.style.joinToString(" ") { it.toString().toLowerCase() }
return when {
node.hasStyle(ContentStyle.TabbedContent) -> div(additionalClasses) {
val secondLevel = node.children.filterIsInstance().flatMap { it.children }
.filterIsInstance().flatMap { it.children }.filterIsInstance()
val firstLevel = node.children.filterIsInstance().flatMap { it.children }
.filterIsInstance()
val renderable = firstLevel.union(secondLevel)
div(classes = "tabs-section") {
attributes["tabs-section"] = "tabs-section"
renderable.forEachIndexed { index, node ->
button(classes = "section-tab") {
if (index == 0) attributes["data-active"] = ""
attributes["data-togglable"] = node.text
text(node.text)
}
}
}
div(classes = "tabs-section-body") {
childrenCallback()
}
}
node.hasStyle(ContentStyle.WithExtraAttributes) -> div() {
node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
childrenCallback()
}
node.dci.kind in setOf(ContentKind.Symbol, ContentKind.Sample) -> div("symbol $additionalClasses") {
childrenCallback()
if (node.hasStyle(TextStyle.Monospace)) copyButton()
}
node.hasStyle(TextStyle.BreakableAfter) -> {
span() { childrenCallback() }
wbr { }
}
node.hasStyle(TextStyle.Breakable) -> {
span("breakable-word") { childrenCallback() }
}
node.hasStyle(TextStyle.Span) -> span() { childrenCallback() }
node.dci.kind == ContentKind.Symbol -> div("symbol $additionalClasses") { childrenCallback() }
node.dci.kind == ContentKind.BriefComment -> div("brief $additionalClasses") { childrenCallback() }
node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") {
filterButtons(node)
childrenCallback()
}
node.hasStyle(TextStyle.Paragraph) -> p(additionalClasses) { childrenCallback() }
node.hasStyle(TextStyle.Block) -> div(additionalClasses) { childrenCallback() }
else -> childrenCallback()
}
}
private fun FlowContent.filterButtons(group: ContentGroup) {
div(classes = "filter-section") {
id = "filter-section"
group.sourceSets.forEach {
button(classes = "platform-tag platform-selector") {
attributes["data-active"] = ""
attributes["data-filter"] = it.sourceSetID
when (it.analysisPlatform.key) {
"common" -> classes = classes + "common-like"
"native" -> classes = classes + "native-like"
"jvm" -> classes = classes + "jvm-like"
"js" -> classes = classes + "js-like"
}
text(it.displayName)
}
}
}
}
private fun FlowContent.copyButton() = span(classes = "top-right-position") {
span("copy-icon") {
unsafe {
raw(
"""""".trimIndent()
)
}
}
copiedPopup("Content copied to clipboard", "popup-to-left")
}
private fun FlowContent.copiedPopup(notificationContent: String, additionalClasses: String = "") =
div("copy-popup-wrapper $additionalClasses") {
unsafe {
raw(
"""
""".trimIndent()
)
}
span {
text(notificationContent)
}
}
override fun FlowContent.buildPlatformDependent(
content: PlatformHintedContent,
pageContext: ContentPage,
sourceSetRestriction: Set?
) =
buildPlatformDependent(
content.sourceSets.filter {
sourceSetRestriction == null || it in sourceSetRestriction
}.map { it to setOf(content.inner) }.toMap(),
pageContext,
content.extra,
content.style
)
private fun FlowContent.buildPlatformDependent(
nodes: Map>,
pageContext: ContentPage,
extra: PropertyContainer = PropertyContainer.empty(),
styles: Set