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