aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/.gitignore2
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt1
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt3
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocContentNodes.kt2
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt102
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt27
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt93
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt1
-rw-r--r--plugins/javadoc/src/main/resources/views/components/bottomNavbar.korte2
-rw-r--r--plugins/javadoc/src/main/resources/views/components/navList.korte2
-rw-r--r--plugins/javadoc/src/main/resources/views/components/subNav.korte16
-rw-r--r--plugins/javadoc/src/main/resources/views/indexPage.korte32
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt125
13 files changed, 365 insertions, 43 deletions
diff --git a/plugins/base/.gitignore b/plugins/base/.gitignore
index d68571db..5c686405 100644
--- a/plugins/base/.gitignore
+++ b/plugins/base/.gitignore
@@ -1,3 +1,5 @@
src/main/resources/dokka/scripts/main.js
src/main/resources/dokka/scripts/main.js.map
+src/main/resources/dokka/scripts/highlight-*
+src/main/resources/dokka/scripts/vendors~*
search-component/dist/ \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
index 20fe9831..01adf767 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPageCreator.kt
@@ -42,6 +42,7 @@ open class JavadocPageCreator(
name = c.name.orEmpty(),
content = contentForClasslike(c),
dri = setOf(c.dri),
+ brief = c.brief(),
signature = signatureForNode(c, jvm),
description = c.descriptionToContentNodes(),
constructors = (c as? WithConstructors)?.constructors?.mapNotNull { it.toJavadocFunction() }.orEmpty(),
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
index 3359b32f..359cfef0 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
@@ -33,6 +33,8 @@ class JavadocLocationProvider(pageRoot: RootPageNode, dokkaContext: DokkaContext
listOfNotNull(page.dri.first().classNames)
else if (page is JavadocPackagePageNode)
listOf(packagePath, "package-summary")
+ else if (page is IndexPage)
+ listOf("index-files", page.name)
else
listOf("index")
else -> emptyList()
@@ -120,6 +122,7 @@ class JavadocLocationProvider(pageRoot: RootPageNode, dokkaContext: DokkaContext
JavadocContentKind.AllClasses -> it.dropLast(1) + "allclasses"
JavadocContentKind.OverviewTree -> it.dropLast(1) + "overview-tree"
JavadocContentKind.PackageTree -> it.dropLast(1) + "package-tree"
+ JavadocContentKind.IndexPage -> it.dropLast(1) + "index-1"
else -> it
}
}?.relativeTo(pathIndex[contextRoot].orEmpty())?.let { if (skipExtension) "$it.html" else it }.orEmpty()
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocContentNodes.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocContentNodes.kt
index d1ccb73e..2b6ebb1c 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocContentNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocContentNodes.kt
@@ -6,7 +6,7 @@ import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.pages.*
enum class JavadocContentKind : Kind {
- AllClasses, OverviewSummary, PackageSummary, Class, OverviewTree, PackageTree
+ AllClasses, OverviewSummary, PackageSummary, Class, OverviewTree, PackageTree, IndexPage
}
abstract class JavadocContentNode(
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
index ec4591c3..7bc6d6d8 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/JavadocPageNodes.kt
@@ -1,6 +1,7 @@
package org.jetbrains.dokka.javadoc.pages
import com.intellij.psi.PsiClass
+import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
import org.jetbrains.dokka.analysis.PsiDocumentableSource
@@ -14,7 +15,6 @@ import org.jetbrains.dokka.pages.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType
-import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
interface JavadocPageNode : ContentPage
@@ -23,6 +23,14 @@ interface WithJavadocExtra<T : Documentable> : WithExtraProperties<T> {
throw IllegalStateException("Merging extras is not applicable for javadoc")
}
+interface WithIndexables {
+ fun getAllIndexables(): List<IndexableJavadocNode>
+}
+
+interface WithBrief {
+ val brief: List<ContentNode>
+}
+
class JavadocModulePageNode(
override val name: String,
override val content: JavadocContentNode,
@@ -54,7 +62,13 @@ class JavadocPackagePageNode(
override val documentable: Documentable? = null,
override val children: List<PageNode> = emptyList(),
override val embeddedResources: List<String> = listOf()
-) : JavadocPageNode {
+) : JavadocPageNode, WithIndexables, IndexableJavadocNode {
+
+ override fun getAllIndexables(): List<IndexableJavadocNode> =
+ children.filterIsInstance<IndexableJavadocNode>().flatMap {
+ if (it is WithIndexables) it.getAllIndexables()
+ else listOf(it)
+ }
override fun modified(
name: String,
@@ -83,44 +97,56 @@ class JavadocPackagePageNode(
children,
embeddedResources
)
+
+ override fun getId(): String = name
+
+ override fun getDRI(): DRI = dri.first()
}
-sealed class AnchorableJavadocNode(open val dri: DRI)
+interface IndexableJavadocNode {
+ fun getId(): String
+ fun getDRI(): DRI
+}
+
+sealed class AnchorableJavadocNode(open val name: String, open val dri: DRI) : IndexableJavadocNode {
+ override fun getId(): String = name
+ override fun getDRI(): DRI = dri
+}
data class JavadocEntryNode(
override val dri: DRI,
- val name: String,
+ override val name: String,
val signature: JavadocSignatureContentNode,
- val brief: List<ContentNode>,
+ override val brief: List<ContentNode>,
override val extra: PropertyContainer<DEnumEntry> = PropertyContainer.empty()
-): AnchorableJavadocNode(dri), WithJavadocExtra<DEnumEntry>
+) : AnchorableJavadocNode(name, dri), WithJavadocExtra<DEnumEntry>, WithBrief
data class JavadocParameterNode(
override val dri: DRI,
- val name: String,
+ override val name: String,
val type: ContentNode,
val description: List<ContentNode>,
val typeBound: Bound,
override val extra: PropertyContainer<DParameter> = PropertyContainer.empty()
-): AnchorableJavadocNode(dri), WithJavadocExtra<DParameter>
+) : AnchorableJavadocNode(name, dri), WithJavadocExtra<DParameter>
data class JavadocPropertyNode(
override val dri: DRI,
- val name: String,
+ override val name: String,
val signature: JavadocSignatureContentNode,
- val brief: List<ContentNode>,
+ override val brief: List<ContentNode>,
override val extra: PropertyContainer<DProperty> = PropertyContainer.empty()
-): AnchorableJavadocNode(dri), WithJavadocExtra<DProperty>
+) : AnchorableJavadocNode(name, dri), WithJavadocExtra<DProperty>, WithBrief
data class JavadocFunctionNode(
val signature: JavadocSignatureContentNode,
- val brief: List<ContentNode>,
+ override val brief: List<ContentNode>,
val description: List<ContentNode>,
val parameters: List<JavadocParameterNode>,
- val name: String,
+ override val name: String,
override val dri: DRI,
override val extra: PropertyContainer<DFunction> = PropertyContainer.empty()
-): AnchorableJavadocNode(dri), WithJavadocExtra<DFunction> {
+) : AnchorableJavadocNode(name, dri), WithJavadocExtra<DFunction>, WithBrief {
val isInherited: Boolean
get() {
val extra = extra[InheritedFunction]
@@ -141,15 +167,22 @@ class JavadocClasslikePageNode(
val entries: List<JavadocEntryNode>,
val classlikes: List<JavadocClasslikePageNode>,
val properties: List<JavadocPropertyNode>,
+ override val brief: List<ContentNode>,
override val documentable: Documentable? = null,
override val children: List<PageNode> = emptyList(),
override val embeddedResources: List<String> = listOf(),
override val extra: PropertyContainer<DClasslike> = PropertyContainer.empty(),
-) : JavadocPageNode, WithJavadocExtra<DClasslike> {
+) : JavadocPageNode, WithJavadocExtra<DClasslike>, IndexableJavadocNode, WithIndexables, WithBrief {
+
+ override fun getAllIndexables(): List<IndexableJavadocNode> =
+ methods + entries + classlikes.map { it.getAllIndexables() }.flatten() + this
val kind: String? = documentable?.kind()
val packageName = dri.first().packageName
+ override fun getId(): String = name
+ override fun getDRI(): DRI = dri.first()
+
override fun modified(
name: String,
children: List<PageNode>
@@ -164,6 +197,7 @@ class JavadocClasslikePageNode(
entries,
classlikes,
properties,
+ brief,
documentable,
children,
embeddedResources,
@@ -188,6 +222,7 @@ class JavadocClasslikePageNode(
entries,
classlikes,
properties,
+ brief,
documentable,
children,
embeddedResources,
@@ -227,6 +262,43 @@ class AllClassesPage(val classes: List<JavadocClasslikePageNode>) : JavadocPageN
}
+class IndexPage(
+ val id: Int,
+ val elements: List<IndexableJavadocNode>,
+ val keys: List<Char>,
+ sourceSet: Set<DisplaySourceSet>
+
+) : JavadocPageNode {
+ override val name: String = "index-$id"
+ override val dri: Set<DRI> = setOf(DRI.topLevel)
+ override val documentable: Documentable? = null
+ override val children: List<PageNode> = emptyList()
+ override val embeddedResources: List<String> = listOf()
+ val title: String = "${keys[id - 1]}-index"
+
+ override val content: ContentNode = EmptyNode(
+ DRI.topLevel,
+ ContentKind.Classlikes,
+ sourceSet
+ )
+
+ override fun modified(
+ name: String,
+ children: List<PageNode>
+ ): PageNode =
+ TODO()
+
+ override fun modified(
+ name: String,
+ content: ContentNode,
+ dri: Set<DRI>,
+ embeddedResources: List<String>,
+ children: List<PageNode>
+ ): ContentPage =
+ TODO()
+
+}
+
class TreeViewPage(
override val name: String,
val packages: List<JavadocPackagePageNode>?,
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
index 42276dd4..a2c3cf22 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
@@ -1,9 +1,11 @@
package org.jetbrains.dokka.javadoc.pages
+import org.jetbrains.dokka.base.renderers.sourceSets
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.transformers.pages.PageTransformer
+import kotlin.collections.HashMap
-val preprocessors = listOf(ResourcesInstaller, TreeViewInstaller, AllClassesPageInstaller)
+val preprocessors = listOf(ResourcesInstaller, TreeViewInstaller, AllClassesPageInstaller, IndexGenerator)
object ResourcesInstaller : PageTransformer {
override fun invoke(input: RootPageNode): RootPageNode = input.modified(
@@ -65,4 +67,27 @@ object AllClassesPageInstaller : PageTransformer {
return input.modified(children = input.children + AllClassesPage(classes))
}
+}
+
+object IndexGenerator: PageTransformer {
+ override fun invoke(input: RootPageNode): RootPageNode {
+ val elements = HashMap<Char, MutableSet<IndexableJavadocNode>>()
+ (input as JavadocModulePageNode).children.filterIsInstance<JavadocPackagePageNode>().forEach {
+ it.getAllIndexables().forEach { d ->
+ val name = when(d) {
+ is JavadocPageNode -> d.name
+ is AnchorableJavadocNode -> d.name
+ else -> null
+ }
+ if (name != null && name.isNotBlank()) {
+ elements.getOrPut(name[0].toUpperCase(), ::mutableSetOf).add(d)
+ }
+ }
+ elements.getOrPut(it.name[0].toUpperCase(), ::mutableSetOf).add(it)
+ }
+ val keys = elements.keys.sortedBy { it }
+ return input.modified(children = input.children + elements.entries.mapIndexed { i, (_, set) ->
+ IndexPage(i + 1, set.sortedBy { it.getId().toLowerCase() }, keys, input.sourceSets())
+ })
+ }
} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
index 49ba1b25..ab12f50c 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
@@ -4,13 +4,15 @@ import org.jetbrains.dokka.javadoc.location.JavadocLocationProvider
import org.jetbrains.dokka.javadoc.pages.*
import org.jetbrains.dokka.javadoc.toNormalized
import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.base.resolvers.local.LocationProvider
+import org.jetbrains.dokka.base.renderers.sourceSets
import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.parent
import org.jetbrains.dokka.links.sureClassNames
import org.jetbrains.dokka.model.ImplementedInterfaces
import org.jetbrains.dokka.model.InheritedFunction
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.utilities.formatToEndWithHtml
import java.nio.file.Paths
internal class JavadocContentToTemplateMapTranslator(
@@ -34,11 +36,12 @@ internal class JavadocContentToTemplateMapTranslator(
is JavadocPackagePageNode -> InnerTranslator(node).templateMapForPackagePageNode(node)
is TreeViewPage -> InnerTranslator(node).templateMapForTreeViewPage(node)
is AllClassesPage -> InnerTranslator(node).templateMapForAllClassesPage(node)
+ is IndexPage -> InnerTranslator(node).templateMapForIndexPage(node)
else -> emptyMap()
}
private fun pathToRoot(node: JavadocPageNode): String {
- return when(node){
+ return when (node) {
is JavadocModulePageNode -> ""
else -> run {
val link = locationProvider.resolve(node, skipExtension = true)
@@ -50,19 +53,29 @@ internal class JavadocContentToTemplateMapTranslator(
}
}
- private inner class InnerTranslator(val contextNode: PageNode) {
+ private inner class InnerTranslator(val contextNode: JavadocPageNode) {
private val htmlTranslator = JavadocContentToHtmlTranslator(locationProvider, context)
- fun templateMapForAllClassesPage(node: AllClassesPage): TemplateMap {
- return mapOf(
+ fun templateMapForAllClassesPage(node: AllClassesPage): TemplateMap =
+ mapOf(
"title" to "All Classes",
"list" to node.classEntries
)
- }
- fun templateMapForTreeViewPage(node: TreeViewPage): TemplateMap {
- return mapOf(
+ fun templateMapForIndexPage(node: IndexPage): TemplateMap =
+ mapOf(
+ "id" to node.id,
+ "title" to node.title,
+ "kind" to "indexPage",
+ "prevLetter" to if (node.id > 1) "index-${node.id - 1}" else "",
+ "nextLetter" to if (node.id < node.keys.size) "index-${node.id + 1}" else "",
+ "dictionary" to node.keys,
+ "elements" to node.elements.map { templateMapForIndexableNode(it) }
+ )
+
+ fun templateMapForTreeViewPage(node: TreeViewPage): TemplateMap =
+ mapOf(
"title" to node.title,
"name" to node.name,
"kind" to node.kind,
@@ -70,23 +83,20 @@ internal class JavadocContentToTemplateMapTranslator(
"classGraph" to node.classGraph,
"interfaceGraph" to node.interfaceGraph
)
- }
- fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap =
- mapOf(
- "kind" to "package"
- ) + templateMapForJavadocContentNode(node.content)
+ fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap = mapOf(
+ "kind" to "package"
+ ) + templateMapForJavadocContentNode(node.content)
- fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap =
- mapOf(
- "brief" to htmlForContentNodes(node.brief, contextNode),
- "description" to htmlForContentNodes(node.description, contextNode),
- "parameters" to node.parameters.map { templateMapForParameterNode(it) },
- "inlineParameters" to node.parameters.joinToString { renderInlineParameter(it) },
- "anchorLink" to locationProvider.anchorForFunctionNode(node),
- "signature" to templateMapForSignatureNode(node.signature),
- "name" to node.name
- )
+ fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap = mapOf(
+ "brief" to htmlForContentNodes(node.brief, contextNode),
+ "description" to htmlForContentNodes(node.description,contextNode),
+ "parameters" to node.parameters.map { templateMapForParameterNode(it) },
+ "inlineParameters" to node.parameters.joinToString { renderInlineParameter(it) },
+ "anchorLink" to locationProvider.anchorForFunctionNode(node),
+ "signature" to templateMapForSignatureNode(node.signature),
+ "name" to node.name
+ )
fun templateMapForClasslikeNode(node: JavadocClasslikePageNode): TemplateMap =
mapOf(
@@ -111,6 +121,43 @@ internal class JavadocContentToTemplateMapTranslator(
"supertypes" to node.supertypes?.let { htmlForContentNode(it, contextNode) }
)
+ private fun IndexableJavadocNode.typeForIndexable() = when (this) {
+ is JavadocClasslikePageNode -> "class"
+ is JavadocFunctionNode -> "function"
+ is JavadocEntryNode -> "enum entry"
+ is JavadocParameterNode -> "parameter"
+ is JavadocPropertyNode -> "property"
+ is JavadocPackagePageNode -> "package"
+ else -> ""
+ }
+
+ fun templateMapForIndexableNode(node: IndexableJavadocNode): TemplateMap {
+ val origin = node.getDRI().parent
+ return mapOf(
+ "address" to locationProvider.resolve(node.getDRI(), contextNode.sourceSets(), contextNode)
+ ?.formatToEndWithHtml().orEmpty(),
+ "type" to node.typeForIndexable(),
+ "isMember" to (node !is JavadocPackagePageNode),
+ "name" to if (node is JavadocFunctionNode) locationProvider.anchorForFunctionNode(node) else node.getId(),
+ "description" to ((node as? WithBrief)?.let {
+ htmlForContentNodes(
+ it.brief,
+ contextNode
+ ).takeIf { desc -> desc.isNotBlank() }
+ } ?: "&nbsp;"),
+ "origin" to origin.indexableOriginSignature(),
+ )
+ }
+
+ private fun DRI.indexableOriginSignature(): String {
+ val packageName = packageName?.takeIf { it.isNotBlank() }
+ val className = classNames?.let {
+ "<a href=${locationProvider.resolve(this, contextNode.sourceSets(), contextNode)
+ ?.formatToEndWithHtml().orEmpty()}>$it</a>"
+ }
+ return listOfNotNull(packageName, className).joinToString(".")
+ }
+
fun templateMapForJavadocContentNode(node: JavadocContentNode): TemplateMap =
when (node) {
is TitleNode -> templateMapForTitleNode(node)
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
index 669f4979..20115ac8 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/renderer/KorteJavadocRenderer.kt
@@ -48,6 +48,7 @@ class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context:
is JavadocClasslikePageNode -> "class.korte"
is AllClassesPage -> "listPage.korte"
is TreeViewPage -> "treePage.korte"
+ is IndexPage -> "indexPage.korte"
else -> ""
}
diff --git a/plugins/javadoc/src/main/resources/views/components/bottomNavbar.korte b/plugins/javadoc/src/main/resources/views/components/bottomNavbar.korte
index 789e3c54..a9d83e5c 100644
--- a/plugins/javadoc/src/main/resources/views/components/bottomNavbar.korte
+++ b/plugins/javadoc/src/main/resources/views/components/bottomNavbar.korte
@@ -13,7 +13,7 @@
</div>
<a id="skip.navbar.bottom">
<!-- -->
- </a></div>
+ </a>
{% set type="bottom" %}{% include "components/subNav.korte" -%}
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</nav>
diff --git a/plugins/javadoc/src/main/resources/views/components/navList.korte b/plugins/javadoc/src/main/resources/views/components/navList.korte
index e27bdecb..d18b44c4 100644
--- a/plugins/javadoc/src/main/resources/views/components/navList.korte
+++ b/plugins/javadoc/src/main/resources/views/components/navList.korte
@@ -22,6 +22,6 @@
<li><a href="package-tree.html">Tree</a></li>
{% end %}
<li>Deprecated</li>
- <li>Index</li>
+ <li><a href="{{ pathToRoot }}index-files/index-1.html">Index</a></li>
<li>Help</li>
</ul> \ No newline at end of file
diff --git a/plugins/javadoc/src/main/resources/views/components/subNav.korte b/plugins/javadoc/src/main/resources/views/components/subNav.korte
index aa0905cf..7869d747 100644
--- a/plugins/javadoc/src/main/resources/views/components/subNav.korte
+++ b/plugins/javadoc/src/main/resources/views/components/subNav.korte
@@ -1,6 +1,20 @@
<div class="subNav">
+{% if kind == "indexPage" %}
+ <ul class="navList">
+ {%- if prevLetter != "" %}
+ <li><a href="{{ prevLetter }}.html">PREV&nbsp;LETTER</a></li>
+ {% else %}
+ <li>PREV&nbsp;LETTER</li>
+ {% endif -%}
+ {%- if nextLetter != "" %}
+ <li><a href="{{ nextLetter }}.html">NEXT&nbsp;LETTER</a></li>
+ {% else %}
+ <li>NEXT&nbsp;LETTER</li>
+ {% endif -%}
+ </ul>
+{% end -%}
<ul class="navList" id="allclasses_navbar_top" style="display: block;">
-<li><a href="{{ pathToRoot }}allclasses.html">All&nbsp;Classes</a></li>
+ <li><a href="{{ pathToRoot }}allclasses.html">All&nbsp;Classes</a></li>
</ul>
{% if type != "bottom" %}
<ul class="navListSearch">
diff --git a/plugins/javadoc/src/main/resources/views/indexPage.korte b/plugins/javadoc/src/main/resources/views/indexPage.korte
new file mode 100644
index 00000000..2881e86d
--- /dev/null
+++ b/plugins/javadoc/src/main/resources/views/indexPage.korte
@@ -0,0 +1,32 @@
+{% extends "components/base.korte" %}
+{% block content %}
+
+<main role="main">
+ <div class="contentContainer">
+ {% for key in dictionary %}
+ <a href="index-{{ loop.index }}.html">{{ key }}</a>&nbsp;
+ {% endfor %}
+ <h2 class="title">{{ dictionary[id - 1] }}</h2>
+ <dl>
+ {% for key in elements %}
+ <dt>
+ {% if key.isMember %}
+ <span class="memberNameLink">
+ {% endif %}
+ <a href="{{ key.address }}">{{ key.name }}</a>
+ {% if key.isMember %}
+ </span> - {{ key.type }} in {{ key.origin|raw }}
+ {% else %}
+ - {{ key.type }} {{ key.name }}
+ {% endif %}
+
+ </dt>
+ <dd>{{ key.description|raw }}</dd>
+
+ {% endfor %}
+ </dl>
+ {% for key in dictionary %}
+ <a href="index-{{ loop.index }}.html">{{ key }}</a>&nbsp;
+ {% endfor %}
+ </div>
+</main> \ No newline at end of file
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
new file mode 100644
index 00000000..9b2c4121
--- /dev/null
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
@@ -0,0 +1,125 @@
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.IndexPage
+import org.jetbrains.dokka.javadoc.renderer.TemplateMap
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+
+internal class JavadocIndexTest : AbstractJavadocTemplateMapTest() {
+
+ @Test
+ fun `generates correct number of index pages`() {
+ testIndexPages { indexPages ->
+ assertEquals(13, indexPages.size)
+ }
+ }
+
+ @Test
+ fun `handles correct number of elements`() {
+ //We are checking whether we will have an additional function for enum classes
+ fun hasAdditionalFunction() =
+ AnnotationTarget.ANNOTATION_CLASS::class.java.methods.any { it.name == "describeConstable" }
+
+ testIndexPages { indexPages ->
+ assertEquals(if (hasAdditionalFunction()) 41 else 40, indexPages.sumBy { it.elements.size })
+ }
+ }
+
+ @Test
+ fun `templateMap for class index`() {
+ testIndexPagesTemplateMaps { templateMaps ->
+ val element = (templateMaps[2]["elements"] as List<TemplateMap>)[1]
+ assertEquals("../package0/ClassA.html", element["address"])
+ assertEquals("ClassA", element["name"])
+ assertEquals("class", element["type"])
+ assertEquals("Documentation for ClassA", element["description"])
+ assertEquals("package0", element["origin"])
+
+ }
+ }
+
+ @Test
+ fun `templateMap for enum entry index`() {
+ testIndexPagesTemplateMaps { templateMaps ->
+ val element = (templateMaps[0]["elements"] as List<TemplateMap>).last()
+ assertEquals("../package1/ClassCEnum.html#A", element["address"])
+ assertEquals("A", element["name"])
+ assertEquals("enum entry", element["type"])
+ assertEquals("&nbsp;", element["description"])
+ assertEquals("package1.<a href=../package1/ClassCEnum.html>ClassCEnum</a>", element["origin"])
+
+ }
+ }
+
+ @Test
+ fun `templateMap for function index`() {
+ testIndexPagesTemplateMaps { templateMaps ->
+ val element = (templateMaps[0]["elements"] as List<TemplateMap>).first()
+ assertEquals("../package0/ClassA.html#a()", element["address"])
+ assertEquals("a()", element["name"])
+ assertEquals("function", element["type"])
+ assertEquals("&nbsp;", element["description"])
+ assertEquals("package0.<a href=../package0/ClassA.html>ClassA</a>", element["origin"])
+
+ }
+ }
+
+ private val query = """
+ /src/source0.kt
+ package package0
+ /**
+ * Documentation for ClassA
+ */
+ class ClassA {
+ fun a() {}
+ fun b() {}
+ fun c() {}
+ }
+
+ /src/source1.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassB {
+ fun d() {}
+ fun e() {}
+ fun f() {}
+ }
+
+ /src/source2.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassC {
+ fun g() {}
+ fun h() {}
+ fun j() {}
+
+ class InnerClass {
+ fun k() {}
+ }
+ }
+
+ /src/source3.kt
+ package package1
+ /**
+ * Documentation for ClassCEnum
+ */
+ enum class ClassCEnum {
+ A, D, E
+ }
+ """.trimIndent()
+
+ private fun testIndexPages(operation: (List<IndexPage>) -> Unit) {
+ testTemplateMapInline(query) {
+ operation(allPagesOfType())
+ }
+ }
+
+ private fun testIndexPagesTemplateMaps(operation: (List<TemplateMap>) -> Unit) =
+ testTemplateMapInline(query) {
+ operation(allPagesOfType<IndexPage>().map { it.templateMap })
+ }
+} \ No newline at end of file