diff options
Diffstat (limited to 'plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt')
-rw-r--r-- | plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt | 125 |
1 files changed, 79 insertions, 46 deletions
diff --git a/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt b/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt index 3c562315..6ef6a6ec 100644 --- a/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt +++ b/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt @@ -4,74 +4,107 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.jetbrains.dokka.Platform import org.jetbrains.dokka.model.DisplaySourceSet import org.jetbrains.dokka.model.dfs +import org.jetbrains.dokka.model.withDescendants import org.jetbrains.dokka.pages.* +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.transformers.pages.PageTransformer import java.util.concurrent.ConcurrentHashMap -data class SearchRecord(val name: String, val description: String? = null, val location: String, val searchKeys: List<String> = listOf(name)) { - companion object { } +typealias PageId = String +typealias Json = String + +data class SearchRecord( + val name: String, + val description: String? = null, + val location: String, + val searchKeys: List<String> = listOf(name) +) { + companion object {} } -open class SearchbarDataInstaller { - private val mapper = jacksonObjectMapper() +open class SearchbarDataInstaller(val context: DokkaContext) : PageTransformer { + data class PageWithId(val id: PageId, val page: ContentPage) { + val displayableSignature = getSymbolSignature(page)?.let { flattenToText(it) } ?: page.name + } - private val pageList = ConcurrentHashMap<String, Pair<String, String>>() + private val mapper = jacksonObjectMapper() - open fun generatePagesList(): String { - val pages = pageList.entries + open fun generatePagesList(pages: Map<PageId, PageWithId>, locationResolver: PageResolver): Json = + pages.entries .filter { it.key.isNotEmpty() } - .sortedWith(compareBy({ it.key }, { it.value.first }, { it.value.second })) + .sortedWith(compareBy({ it.key }, { it.value.displayableSignature })) .groupBy { it.key.substringAfterLast(".") } .entries .flatMap { entry -> entry.value.map { subentry -> - val name = subentry.value.first createSearchRecord( - name = name, + name = subentry.value.displayableSignature, description = subentry.key, - location = subentry.value.second, - searchKeys = listOf(entry.key, name) + location = resolveLocation(locationResolver, subentry.value.page).orEmpty(), + searchKeys = listOf(entry.key, subentry.value.displayableSignature) ) } - } - return mapper.writeValueAsString(pages) - } + }.run { mapper.writeValueAsString(this) } - open fun createSearchRecord(name: String, description: String?, location: String, searchKeys: List<String>): SearchRecord = + open fun createSearchRecord( + name: String, + description: String?, + location: String, + searchKeys: List<String> + ): SearchRecord = SearchRecord(name, description, location, searchKeys) + open fun processPage(page: PageNode): PageWithId? = + when (page) { + is ContentPage -> page.takeIf { page !is ModulePageNode && page !is PackagePageNode }?.documentable + ?.let { documentable -> + listOfNotNull( + documentable.dri.packageName, + documentable.dri.classNames, + documentable.dri.callable?.name + ).takeIf { it.isNotEmpty() }?.joinToString(".") + }?.let { id -> + PageWithId(id, page) + } + else -> null + } - private fun getSymbolSignature(page: ContentPage) = page.content.dfs { it.dci.kind == ContentKind.Symbol } + private fun resolveLocation(locationResolver: PageResolver, page: ContentPage): String? = + locationResolver(page, null).also { location -> + if (location.isNullOrBlank()) context.logger.warn("Cannot resolve path for ${page.dri}") + } - private fun flattenToText(node: ContentNode): String { - fun getContentTextNodes(node: ContentNode, sourceSetRestriction: DisplaySourceSet): List<ContentText> = - when (node) { - is ContentText -> listOf(node) - is ContentComposite -> node.children - .filter { sourceSetRestriction in it.sourceSets } - .flatMap { getContentTextNodes(it, sourceSetRestriction) } - .takeIf { node.dci.kind != ContentKind.Annotations } - .orEmpty() - else -> emptyList() - } + override fun invoke(input: RootPageNode): RootPageNode { + val page = RendererSpecificResourcePage( + name = "scripts/pages.js", + children = emptyList(), + strategy = RenderingStrategy.PageLocationResolvableWrite { resolver -> + input.withDescendants().fold(emptyMap<PageId, PageWithId>()) { pageList, page -> + processPage(page)?.let { pageList + Pair(it.id, it) } ?: pageList + }.run { + """var pages = ${generatePagesList(this, resolver)}""" + } + }) - val sourceSetRestriction = - node.sourceSets.find { it.platform == Platform.common } ?: node.sourceSets.first() - return getContentTextNodes(node, sourceSetRestriction).joinToString("") { it.text } + return input.modified(children = input.children + page) } +} + +private fun getSymbolSignature(page: ContentPage) = page.content.dfs { it.dci.kind == ContentKind.Symbol } - open fun processPage(page: ContentPage, link: String) { - val signature = getSymbolSignature(page) - val textNodes = signature?.let { flattenToText(it) } - val documentable = page.documentable - if (documentable != null) { - listOf( - documentable.dri.packageName, - documentable.dri.classNames, - documentable.dri.callable?.name - ).filter { !it.isNullOrEmpty() } - .takeIf { it.isNotEmpty() } - ?.joinToString(".") - ?.let { id -> pageList.put(id, Pair(textNodes ?: page.name, link)) } +private fun flattenToText(node: ContentNode): String { + fun getContentTextNodes(node: ContentNode, sourceSetRestriction: DisplaySourceSet): List<ContentText> = + when (node) { + is ContentText -> listOf(node) + is ContentComposite -> node.children + .filter { sourceSetRestriction in it.sourceSets } + .flatMap { getContentTextNodes(it, sourceSetRestriction) } + .takeIf { node.dci.kind != ContentKind.Annotations } + .orEmpty() + else -> emptyList() } - } -} + + val sourceSetRestriction = + node.sourceSets.find { it.platform == Platform.common } ?: node.sourceSets.first() + return getContentTextNodes(node, sourceSetRestriction).joinToString("") { it.text } +}
\ No newline at end of file |