diff options
author | Marcin Aman <maman@virtuslab.com> | 2020-07-09 10:45:06 +0200 |
---|---|---|
committer | Paweł Marks <Kordyjan@users.noreply.github.com> | 2020-07-16 13:17:39 +0200 |
commit | 04cf1cdd3a909fa62e5ffda5b7d04695c749177e (patch) | |
tree | 5c38372dd70f5528bf55c084a1893a7af8e41359 /plugins/javadoc/src/main/kotlin | |
parent | 42c6bcdbd564628907491289555c6d6713294fef (diff) | |
download | dokka-04cf1cdd3a909fa62e5ffda5b7d04695c749177e.tar.gz dokka-04cf1cdd3a909fa62e5ffda5b7d04695c749177e.tar.bz2 dokka-04cf1cdd3a909fa62e5ffda5b7d04695c749177e.zip |
Implement javadoc search
Diffstat (limited to 'plugins/javadoc/src/main/kotlin')
8 files changed, 358 insertions, 39 deletions
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt index 6fe18001..7420f78e 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt @@ -4,11 +4,11 @@ import javadoc.pages.* import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet import org.jetbrains.dokka.Platform import org.jetbrains.dokka.base.signatures.SignatureProvider -import org.jetbrains.dokka.base.signatures.function import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.doc.Description +import org.jetbrains.dokka.model.doc.Index import org.jetbrains.dokka.model.doc.Param import org.jetbrains.dokka.model.doc.TagWrapper import org.jetbrains.dokka.model.properties.PropertyContainer @@ -51,7 +51,8 @@ open class JavadocPageCreator( it.dri, it.name, signatureForNode(it, jvm), - it.descriptionToContentNodes(jvm) + it.descriptionToContentNodes(jvm), + PropertyContainer.withAll(it.indexesInDocumentation()) ) }.orEmpty(), classlikes = c.classlikes.mapNotNull { pageForClasslike(it) }, @@ -60,11 +61,12 @@ open class JavadocPageCreator( it.dri, it.name, signatureForNode(it, jvm), - it.descriptionToContentNodes(jvm) + it.descriptionToContentNodes(jvm), + PropertyContainer.withAll(it.indexesInDocumentation()) ) }, documentable = c, - extras = (c as? WithExtraProperties<Documentable>)?.extra ?: PropertyContainer.empty() + extra = ((c as? WithExtraProperties<Documentable>)?.extra ?: PropertyContainer.empty()) + c.indexesInDocumentation() ) } @@ -148,11 +150,12 @@ open class JavadocPageCreator( type = type, description = it.brief(), typeBound = it.type, - dri = it.dri + dri = it.dri, + extra = PropertyContainer.withAll(it.indexesInDocumentation()) ) } }, - extras = extra + extra = extra + indexesInDocumentation() ) } @@ -212,5 +215,24 @@ open class JavadocPageCreator( private fun signatureForNode(documentable: Documentable, sourceSet: DokkaSourceSet): JavadocSignatureContentNode = signatureProvider.signature(documentable).nodeForJvm(sourceSet).asJavadocNode() + + private fun Documentable.indexesInDocumentation(): JavadocIndexExtra { + val indexes = documentation[highestJvmSourceSet]?.withDescendants()?.filterIsInstance<Index>()?.toList().orEmpty() + return JavadocIndexExtra( + indexes.map { + ContentGroup( + children = DocTagToContentConverter.buildContent( + it, + DCI(setOf(dri), JavadocContentKind.OverviewSummary), + sourceSets.toSet() + ), + dci = DCI(setOf(dri), JavadocContentKind.OverviewSummary), + sourceSets = sourceSets.toSet(), + style = emptySet(), + extra = PropertyContainer.empty() + ) + } + ) + } } diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocIndexExtra.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocIndexExtra.kt new file mode 100644 index 00000000..3ae04cae --- /dev/null +++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocIndexExtra.kt @@ -0,0 +1,10 @@ +package javadoc.pages + +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.model.properties.ExtraProperty +import org.jetbrains.dokka.pages.ContentNode + +data class JavadocIndexExtra(val index: List<ContentNode>) : ExtraProperty<Documentable> { + override val key: ExtraProperty.Key<Documentable, *> = JavadocIndexExtra + companion object : ExtraProperty.Key<Documentable, JavadocIndexExtra> +}
\ No newline at end of file diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt index 216b9319..daa4fda5 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt @@ -9,6 +9,7 @@ import org.jetbrains.dokka.base.renderers.sourceSets import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.properties.PropertyContainer +import org.jetbrains.dokka.model.properties.WithExtraProperties import org.jetbrains.dokka.pages.* import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind @@ -17,6 +18,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance interface JavadocPageNode : ContentPage +interface WithJavadocExtra<T : Documentable> : WithExtraProperties<T> { + override fun withNewExtras(newExtras: PropertyContainer<T>): T = + throw IllegalStateException("Merging extras is not applicable for javadoc") +} + class JavadocModulePageNode( override val name: String, override val content: JavadocContentNode, @@ -85,23 +91,26 @@ data class JavadocEntryNode( override val dri: DRI, val name: String, val signature: JavadocSignatureContentNode, - val brief: List<ContentNode> -): AnchorableJavadocNode(dri) + val brief: List<ContentNode>, + override val extra: PropertyContainer<DEnumEntry> = PropertyContainer.empty() +): AnchorableJavadocNode(dri), WithJavadocExtra<DEnumEntry> data class JavadocParameterNode( override val dri: DRI, val name: String, val type: ContentNode, val description: List<ContentNode>, - val typeBound: Bound -): AnchorableJavadocNode(dri) + val typeBound: Bound, + override val extra: PropertyContainer<DParameter> = PropertyContainer.empty() +): AnchorableJavadocNode(dri), WithJavadocExtra<DParameter> data class JavadocPropertyNode( override val dri: DRI, val name: String, val signature: JavadocSignatureContentNode, - val brief: List<ContentNode> -): AnchorableJavadocNode(dri) + val brief: List<ContentNode>, + override val extra: PropertyContainer<DProperty> = PropertyContainer.empty() +): AnchorableJavadocNode(dri), WithJavadocExtra<DProperty> data class JavadocFunctionNode( val signature: JavadocSignatureContentNode, @@ -109,8 +118,16 @@ data class JavadocFunctionNode( val parameters: List<JavadocParameterNode>, val name: String, override val dri: DRI, - val extras: PropertyContainer<DFunction> = PropertyContainer.empty() -): AnchorableJavadocNode(dri) + override val extra: PropertyContainer<DFunction> = PropertyContainer.empty() +): AnchorableJavadocNode(dri), WithJavadocExtra<DFunction> { + val isInherited: Boolean + get() { + val extra = extra[InheritedFunction] + return extra?.inheritedFrom?.keys?.firstOrNull { it.analysisPlatform == Platform.jvm }?.let { jvm -> + extra.isInherited(jvm) + } ?: false + } +} class JavadocClasslikePageNode( override val name: String, @@ -126,8 +143,8 @@ class JavadocClasslikePageNode( override val documentable: Documentable? = null, override val children: List<PageNode> = emptyList(), override val embeddedResources: List<String> = listOf(), - val extras: PropertyContainer<Documentable>, -) : JavadocPageNode { + override val extra: PropertyContainer<DClasslike> = PropertyContainer.empty(), +) : JavadocPageNode, WithJavadocExtra<DClasslike> { val kind: String? = documentable?.kind() val packageName = dri.first().packageName @@ -149,7 +166,7 @@ class JavadocClasslikePageNode( documentable, children, embeddedResources, - extras + extra ) override fun modified( @@ -173,7 +190,7 @@ class JavadocClasslikePageNode( documentable, children, embeddedResources, - extras + extra ) } diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlPreprocessors.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlPreprocessors.kt index 3ccd1d71..18096ad4 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlPreprocessors.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlPreprocessors.kt @@ -35,7 +35,12 @@ object TreeViewInstaller : PageTransformer { root = root ) - return node.modified(children = node.children.map { node -> install(node, root) } + overviewTree) as JavadocModulePageNode + return node.modified(children = node.children.map { node -> + install( + node, + root + ) + } + overviewTree) as JavadocModulePageNode } private fun installPackageTreeNode(node: JavadocPackagePageNode, root: RootPageNode): JavadocPackagePageNode { diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt index aeff192a..ceb6f9ad 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt @@ -4,6 +4,7 @@ import javadoc.location.JavadocLocationProvider import javadoc.pages.JavadocSignatureContentNode import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.utilities.formatToEndWithHtml import org.jetbrains.dokka.utilities.htmlEscape internal class JavadocContentToHtmlTranslator( @@ -13,21 +14,30 @@ internal class JavadocContentToHtmlTranslator( fun htmlForContentNode(node: ContentNode, relative: PageNode?): String = when (node) { - is ContentGroup -> htmlForContentNodes(node.children, relative) - is ContentText -> node.text.htmlEscape() + is ContentGroup -> htmlForContentNodes(node.children, node.style, relative) + is ContentText -> buildText(node) is ContentDRILink -> buildLink( locationProvider.resolve(node.address, node.sourceSets, relative), - htmlForContentNodes(node.children, relative) + htmlForContentNodes(node.children, node.style, relative) ) - is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, relative)) + is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, node.style, relative)) is ContentCode -> htmlForCode(node.children) is JavadocSignatureContentNode -> htmlForSignature(node, relative) else -> "" } - fun htmlForContentNodes(list: List<ContentNode>, relative: PageNode?) = + fun htmlForContentNodes(list: List<ContentNode>, styles: Set<Style>, relative: PageNode?) = list.joinToString(separator = "") { htmlForContentNode(it, relative) } + private fun buildText(node: ContentText): String { + val escapedText = node.text.htmlEscape() + return if (node.style.contains(ContentStyle.InDocumentationAnchor)) { + """<em><a id="$escapedText" class="searchTagResult">${escapedText}</a></em>""" + } else { + escapedText + } + } + private fun htmlForCode(code: List<ContentNode>): String = code.map { element -> when (element) { is ContentText -> element.text @@ -49,7 +59,5 @@ internal class JavadocContentToHtmlTranslator( fun buildLink(address: String, content: String) = """<a href=${address.formatToEndWithHtml()}>$content</a>""" - private fun String.formatToEndWithHtml() = - if (endsWith(".html") || contains(Regex("\\.html#"))) this else "$this.html" } }
\ No newline at end of file diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt index 56df469b..f59fd27e 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt @@ -129,16 +129,11 @@ internal class JavadocContentToTemplateMapTranslator( ) private fun templateMapForImplementedInterfaces(node: JavadocClasslikePageNode) = - node.extras[ImplementedInterfaces]?.interfaces?.entries?.firstOrNull { it.key.analysisPlatform == Platform.jvm }?.value?.map { it.displayable() } // TODO: REMOVE HARDCODED JVM DEPENDENCY + node.extra[ImplementedInterfaces]?.interfaces?.entries?.firstOrNull { it.key.analysisPlatform == Platform.jvm }?.value?.map { it.displayable() } // TODO: REMOVE HARDCODED JVM DEPENDENCY .orEmpty() private fun templateMapForClasslikeMethods(nodes: List<JavadocFunctionNode>): TemplateMap { - val (inherited, own) = nodes.partition { - val extra = it.extras[InheritedFunction] - extra?.inheritedFrom?.keys?.firstOrNull { it.analysisPlatform == Platform.jvm }?.let { jvm -> - extra.isInherited(jvm) - } ?: false - } + val (inherited, own) = nodes.partition { it.isInherited } return mapOf( "own" to own.map { templateMapForFunctionNode(it) }, "inherited" to inherited.map { templateMapForInheritedMethod(it) } @@ -152,7 +147,7 @@ internal class JavadocContentToTemplateMapTranslator( } private fun templateMapForInheritedMethod(node: JavadocFunctionNode): TemplateMap { - val inheritedFrom = node.extras[InheritedFunction]?.inheritedFrom + val inheritedFrom = node.extra[InheritedFunction]?.inheritedFrom return mapOf( "inheritedFrom" to inheritedFrom?.entries?.firstOrNull { it.key.analysisPlatform == Platform.jvm }?.value?.displayable() // TODO: REMOVE HARDCODED JVM DEPENDENCY .orEmpty(), @@ -219,7 +214,7 @@ internal class JavadocContentToTemplateMapTranslator( htmlTranslator.htmlForContentNode(node, relativeNode) private fun htmlForContentNodes(nodes: List<ContentNode>, relativeNode: PageNode) = - htmlTranslator.htmlForContentNodes(nodes, relativeNode) + htmlTranslator.htmlForContentNodes(nodes, emptySet(), relativeNode) } private fun DRI.displayable(): String = "${packageName}.${sureClassNames}" diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt index f7d75924..80d5a2b7 100644 --- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt +++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt @@ -40,6 +40,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: locationProvider = context.plugin<JavadocPlugin>().querySingle { locationProviderFactory }.getLocationProvider(newRoot) runBlocking(Dispatchers.IO) { renderModulePageNode(newRoot as JavadocModulePageNode) + SearchScriptsCreator(locationProvider).invoke(newRoot).forEach { renderSpecificPage(it, "") } } } @@ -80,7 +81,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: private fun CoroutineScope.renderSpecificPage(node: RendererSpecificPage, path: String) = launch { when (val strategy = node.strategy) { is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, "") - is RenderingStrategy.Write -> outputWriter.writeHtml(path, strategy.text) + is RenderingStrategy.Write -> outputWriter.writeHtml(node.name, strategy.text) is RenderingStrategy.Callback -> outputWriter.writeResources( path, strategy.instructions(this@KorteJavadocRenderer, node) @@ -94,7 +95,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: private fun DRI.toLink(context: PageNode? = null) = locationProvider.resolve(this, emptySet(), context) - private suspend fun OutputWriter.writeHtml(path: String, text: String) = write(path, text, ".html") + private suspend fun OutputWriter.writeHtml(path: String, text: String) = write(path, text, "") private fun CoroutineScope.writeFromTemplate( writer: OutputWriter, path: String, @@ -102,7 +103,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: args: List<Pair<String, *>> ) = launch { val tmp = templateRenderer.render(template, *(args.toTypedArray())) - writer.writeHtml(path, tmp) + writer.writeHtml("$path.html", tmp) } private fun getTemplateConfig() = TemplateConfig().also { config -> @@ -118,7 +119,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: (buildLink( locationProvider.resolve(link, contextRoot), link.name - ) to contentToHtmlTranslator.htmlForContentNodes(doc, contextRoot)).pairToTag().trim() + ) to contentToHtmlTranslator.htmlForContentNodes(doc, emptySet(), contextRoot)).pairToTag().trim() }, TeFunction("createListRow") { args -> val link = args.first() as LinkJavadocListEntry diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/SearchScriptsCreator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/SearchScriptsCreator.kt new file mode 100644 index 00000000..28b88909 --- /dev/null +++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/SearchScriptsCreator.kt @@ -0,0 +1,261 @@ +package javadoc.renderer + +import javadoc.location.JavadocLocationProvider +import javadoc.pages.* +import javadoc.renderer.SearchRecord.Companion.allTypes +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.base.renderers.sourceSets +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.model.InheritedFunction +import org.jetbrains.dokka.model.doc.Index +import org.jetbrains.dokka.model.properties.WithExtraProperties +import org.jetbrains.dokka.pages.* +import org.jetbrains.dokka.utilities.formatToEndWithHtml +import org.jetbrains.dokka.utilities.htmlEscape +import java.lang.StringBuilder + +class SearchScriptsCreator(private val locationProvider: JavadocLocationProvider) { + + fun invoke(input: RootPageNode): List<RendererSpecificPage> { + val data = when (input) { + is JavadocModulePageNode -> processModules(listOf(input)) + else -> SearchData() + } + val serializer = SearchRecordJsonSerializer() + + val modules = RendererSpecificResourcePage( + name = "module-search-index.js", + children = emptyList(), + strategy = RenderingStrategy.Write(serializer.serialize(data.moduleRecords, "moduleSearchIndex")) + ) + + val packages = RendererSpecificResourcePage( + name = "package-search-index.js", + children = emptyList(), + strategy = RenderingStrategy.Write(serializer.serialize(data.packageRecords, "packageSearchIndex")) + ) + + val types = RendererSpecificResourcePage( + name = "type-search-index.js", + children = emptyList(), + strategy = RenderingStrategy.Write(serializer.serialize(data.typeRecords, "typeSearchIndex")) + ) + + val members = RendererSpecificResourcePage( + name = "member-search-index.js", + children = emptyList(), + strategy = RenderingStrategy.Write(serializer.serialize(data.memberRecords, "memberSearchIndex")) + ) + + val indexes = RendererSpecificResourcePage( + name = "tag-search-index.js", + children = emptyList(), + strategy = RenderingStrategy.Write(serializer.serialize(data.searchIndexes, "tagSearchIndex")) + ) + + return listOf(modules, packages, types, members, indexes) + } + + private fun processModules(input: List<JavadocModulePageNode>): SearchData { + val modules = SearchData(moduleRecords = input.map { SearchRecord(l = it.name, url = locationProvider.resolve(it).formatToEndWithHtml()) }) + val processablePackages = input.flatMap { it.children.filterIsInstance<JavadocPackagePageNode>() } + return processPackages(processablePackages, modules) + } + + private fun processPackages(input: List<JavadocPackagePageNode>, accumulator: SearchData): SearchData { + val packages = input.map { SearchRecord(l = it.name, url = locationProvider.resolve(it).formatToEndWithHtml()) } + SearchRecord.allPackages + val types = input.flatMap { + it.children.filterIsInstance<JavadocClasslikePageNode>().map { classlike -> it to classlike } + } + val updated = accumulator.copy(packageRecords = packages) + return processTypes(types, updated) + } + + private fun processTypes( + input: List<Pair<JavadocPackagePageNode, JavadocClasslikePageNode>>, + accumulator: SearchData + ): SearchData { + val types = input.map { + SearchRecord( + p = it.first.name, + l = it.second.name, + url = locationProvider.resolve(it.second).formatToEndWithHtml() + ) + } + allTypes + val updated = accumulator.copy(typeRecords = types) + return processMembers(input, updated).copy(searchIndexes = indexSearchForClasslike(input)) + } + + private fun processMembers( + input: List<Pair<JavadocPackagePageNode, JavadocClasslikePageNode>>, + accumulator: SearchData + ): SearchData { + val functions = input.flatMap { + (it.second.constructors + it.second.methods).withoutInherited().map { function -> + SearchRecordCreator.function( + packageName = it.first.name, + classlikeName = it.second.name, + input = function, + url = locationProvider.resolve(function.dri, it.first.sourceSets()) + ) + } + } + + val properties = input.flatMap { + it.second.properties.map { property -> + SearchRecordCreator.property( + packageName = it.first.name, + classlikeName = it.second.name, + property, + locationProvider.resolve(property.dri, it.first.sourceSets()) + ) + } + } + + val entries = input.flatMap { + it.second.entries.map { entry -> + SearchRecordCreator.entry( + packageName = it.first.name, + classlikeName = it.second.name, + entry, + locationProvider.resolve(entry.dri, it.first.sourceSets()) + ) + } + } + + return accumulator.copy(memberRecords = functions + properties + entries) + } + + private fun indexSearchForClasslike( + input: List<Pair<JavadocPackagePageNode, JavadocClasslikePageNode>>, + ): List<SearchRecord> { + val indexesForClasslike = input.flatMap { + val indexes = it.second.indexes() + indexes.map { index -> + val label = renderNode(index) + SearchRecord( + p = it.first.name, + c = it.second.name, + l = label, + url = resolveUrlForSearchIndex(it.second.dri.first(), it.second.sourceSets(), label) + ) + } + } + + val indexesForMemberNodes = input.flatMap { packageWithClasslike -> + (packageWithClasslike.second.constructors + + packageWithClasslike.second.methods.withoutInherited() + + packageWithClasslike.second.properties + + packageWithClasslike.second.entries + ).map { it to it.indexes() } + .flatMap { entryWithIndex -> + entryWithIndex.second.map { + val label = renderNode(it) + SearchRecord( + p = packageWithClasslike.first.name, + c = packageWithClasslike.second.name, + l = label, + url = resolveUrlForSearchIndex( + entryWithIndex.first.dri, + packageWithClasslike.second.sourceSets(), + label + ) + ) + } + } + } + + return indexesForClasslike + indexesForMemberNodes + } + + private fun <T : Documentable> WithJavadocExtra<T>.indexes(): List<ContentNode> = extra[JavadocIndexExtra]?.index.orEmpty() + + private fun List<JavadocFunctionNode>.withoutInherited(): List<JavadocFunctionNode> = filter { !it.isInherited } + + private fun resolveUrlForSearchIndex(dri: DRI, sourceSets: Set<DokkaConfiguration.DokkaSourceSet>, label: String): String = + locationProvider.resolve(dri, sourceSets).formatToEndWithHtml() + "#" + label +} + +private data class SearchRecord( + val p: String? = null, + val c: String? = null, + val l: String, + val url: String? = null +) { + companion object { + val allPackages = SearchRecord(l = "All packages", url = "index.html") + val allTypes = SearchRecord(l = "All classes", url = "allclasses.html") + } +} + +private object SearchRecordCreator { + fun function( + packageName: String, + classlikeName: String, + input: JavadocFunctionNode, + url: String + ): SearchRecord = + SearchRecord( + p = packageName, + c = classlikeName, + l = input.name + input.parameters.joinToString( + prefix = "(", + postfix = ")" + ) { renderNode(it.type) }, + url = url.formatToEndWithHtml() + ) + + fun property( + packageName: String, + classlikeName: String, + input: JavadocPropertyNode, + url: String + ): SearchRecord = + SearchRecord( + p = packageName, + c = classlikeName, + l = input.name, + url = url.formatToEndWithHtml() + ) + + fun entry(packageName: String, classlikeName: String, input: JavadocEntryNode, url: String): SearchRecord = + SearchRecord( + p = packageName, + c = classlikeName, + l = input.name, + url = url.formatToEndWithHtml() + ) +} + +private data class SearchData( + val moduleRecords: List<SearchRecord> = emptyList(), + val packageRecords: List<SearchRecord> = emptyList(), + val typeRecords: List<SearchRecord> = emptyList(), + val memberRecords: List<SearchRecord> = emptyList(), + val searchIndexes: List<SearchRecord> = emptyList() +) + +private class SearchRecordJsonSerializer { + fun serialize(record: SearchRecord): String { + val serialized = StringBuilder() + serialized.append("{") + with(record) { + if (p != null) serialized.append("\"p\":\"$p\",") + if (c != null) serialized.append("\"c\":\"$c\",") + serialized.append("\"l\":\"$l\"") + if (url != null) serialized.append(",\"url\":\"$url\"") + } + serialized.append("}") + return serialized.toString() + } + + fun serialize(records: List<SearchRecord>, variable: String): String = + "var " + variable + " = " + records.joinToString(prefix = "[", postfix = "]") { serialize(it) } +} + +private fun renderNode(node: ContentNode): String = + when (node) { + is ContentText -> node.text + else -> node.children.joinToString(separator = "") { renderNode(it) } + }
\ No newline at end of file |