aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2023-02-24 17:44:24 +0200
committerGitHub <noreply@github.com>2023-02-24 17:44:24 +0200
commit1040288ca76e070445f1400df2fcc5a56310be28 (patch)
tree52bed40e8a320f0835540b0cd38ea1899800e395
parent8d23340d1c377b8f490cdee3c2c874453d321dd8 (diff)
downloaddokka-1040288ca76e070445f1400df2fcc5a56310be28.tar.gz
dokka-1040288ca76e070445f1400df2fcc5a56310be28.tar.bz2
dokka-1040288ca76e070445f1400df2fcc5a56310be28.zip
Reorganize tabs for Classlike (#2764)
-rw-r--r--core/api/core.api33
-rw-r--r--core/content-matcher-test-utils/api/content-matcher-test-utils.api2
-rw-r--r--core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt18
-rw-r--r--core/src/main/kotlin/model/Documentable.kt2
-rw-r--r--core/src/main/kotlin/model/documentableUtils.kt2
-rw-r--r--core/src/main/kotlin/pages/ContentNodes.kt9
-rw-r--r--core/src/main/kotlin/pages/contentNodeProperties.kt20
-rw-r--r--plugins/base/api/base.api15
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt5
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt30
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt160
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt405
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DescriptionSections.kt2
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt52
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/platform-content-handler.js52
-rw-r--r--plugins/base/src/main/resources/dokka/styles/style.css10
-rw-r--r--plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt171
-rw-r--r--plugins/base/src/test/kotlin/enums/KotlinEnumsTest.kt2
-rw-r--r--plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt12
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/CoverPageTest.kt2
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt2
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/TabbedContentTest.kt111
-rw-r--r--plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt19
-rw-r--r--plugins/base/src/test/kotlin/signatures/SignatureTest.kt4
-rw-r--r--plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt17
-rw-r--r--plugins/base/src/test/kotlin/transformers/MergeImplicitExpectActualDeclarationsTest.kt10
-rw-r--r--plugins/base/src/test/kotlin/utils/contentUtils.kt95
-rw-r--r--plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt64
28 files changed, 873 insertions, 453 deletions
diff --git a/core/api/core.api b/core/api/core.api
index f51d7043..4c755aae 100644
--- a/core/api/core.api
+++ b/core/api/core.api
@@ -1460,6 +1460,7 @@ public final class org/jetbrains/dokka/model/DocumentableUtilsKt {
public static final fun filter (Lorg/jetbrains/dokka/model/DTypeParameter;Ljava/util/Set;)Lorg/jetbrains/dokka/model/DTypeParameter;
public static final fun filtered (Ljava/util/Map;Ljava/util/Set;)Ljava/util/Map;
public static final fun filtered (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;)Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;
+ public static final fun isExtension (Lorg/jetbrains/dokka/model/Documentable;)Z
}
public final class org/jetbrains/dokka/model/DoubleConstant : org/jetbrains/dokka/model/Expression {
@@ -3469,6 +3470,18 @@ public abstract interface class org/jetbrains/dokka/model/properties/WithExtraPr
public abstract fun withNewExtras (Lorg/jetbrains/dokka/model/properties/PropertyContainer;)Ljava/lang/Object;
}
+public final class org/jetbrains/dokka/pages/BasicTabbedContentType : java/lang/Enum, org/jetbrains/dokka/pages/TabbedContentType {
+ public static final field CONSTRUCTOR Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field ENTRY Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field EXTENSION_FUNCTION Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field EXTENSION_PROPERTY Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field FUNCTION Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field PROPERTY Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static final field TYPE Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+ public static fun values ()[Lorg/jetbrains/dokka/pages/BasicTabbedContentType;
+}
+
public abstract interface class org/jetbrains/dokka/pages/ClasslikePage : org/jetbrains/dokka/pages/ContentPage, org/jetbrains/dokka/pages/WithDocumentables {
}
@@ -4248,17 +4261,12 @@ public abstract class org/jetbrains/dokka/pages/RootPageNode : org/jetbrains/dok
}
public final class org/jetbrains/dokka/pages/SimpleAttr : org/jetbrains/dokka/model/properties/ExtraProperty {
- public static final field Companion Lorg/jetbrains/dokka/pages/SimpleAttr$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public final fun getExtraKey ()Ljava/lang/String;
public final fun getExtraValue ()Ljava/lang/String;
public fun getKey ()Lorg/jetbrains/dokka/model/properties/ExtraProperty$Key;
}
-public final class org/jetbrains/dokka/pages/SimpleAttr$Companion {
- public final fun header (Ljava/lang/String;)Lorg/jetbrains/dokka/pages/SimpleAttr;
-}
-
public final class org/jetbrains/dokka/pages/SimpleAttr$SimpleAttrKey : org/jetbrains/dokka/model/properties/ExtraProperty$Key {
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
@@ -4282,6 +4290,21 @@ public final class org/jetbrains/dokka/pages/SymbolContentKind : java/lang/Enum,
public static fun values ()[Lorg/jetbrains/dokka/pages/SymbolContentKind;
}
+public abstract interface class org/jetbrains/dokka/pages/TabbedContentType {
+}
+
+public final class org/jetbrains/dokka/pages/TabbedContentTypeExtra : org/jetbrains/dokka/model/properties/ExtraProperty {
+ public static final field Companion Lorg/jetbrains/dokka/pages/TabbedContentTypeExtra$Companion;
+ public fun <init> (Lorg/jetbrains/dokka/pages/TabbedContentType;)V
+ public fun getKey ()Lorg/jetbrains/dokka/model/properties/ExtraProperty$Key;
+ public final fun getValue ()Lorg/jetbrains/dokka/pages/TabbedContentType;
+}
+
+public final class org/jetbrains/dokka/pages/TabbedContentTypeExtra$Companion : org/jetbrains/dokka/model/properties/ExtraProperty$Key {
+ public synthetic fun mergeStrategyFor (Ljava/lang/Object;Ljava/lang/Object;)Lorg/jetbrains/dokka/model/properties/MergeStrategy;
+ public fun mergeStrategyFor (Lorg/jetbrains/dokka/pages/TabbedContentTypeExtra;Lorg/jetbrains/dokka/pages/TabbedContentTypeExtra;)Lorg/jetbrains/dokka/model/properties/MergeStrategy;
+}
+
public final class org/jetbrains/dokka/pages/TextStyle : java/lang/Enum, org/jetbrains/dokka/pages/Style {
public static final field Block Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Bold Lorg/jetbrains/dokka/pages/TextStyle;
diff --git a/core/content-matcher-test-utils/api/content-matcher-test-utils.api b/core/content-matcher-test-utils/api/content-matcher-test-utils.api
index 0a7f153b..58881a15 100644
--- a/core/content-matcher-test-utils/api/content-matcher-test-utils.api
+++ b/core/content-matcher-test-utils/api/content-matcher-test-utils.api
@@ -30,6 +30,8 @@ public final class matchers/content/ContentMatchersDslKt {
public static final fun platformHinted (Lmatchers/content/ContentMatcherBuilder;Lkotlin/jvm/functions/Function1;)V
public static final fun skipAllNotMatching (Lmatchers/content/ContentMatcherBuilder;)V
public static final fun somewhere (Lmatchers/content/ContentMatcherBuilder;Lkotlin/jvm/functions/Function1;)V
+ public static final fun tab (Lmatchers/content/ContentMatcherBuilder;Lorg/jetbrains/dokka/pages/TabbedContentType;Lkotlin/jvm/functions/Function1;)V
+ public static final fun tabbedGroup (Lmatchers/content/ContentMatcherBuilder;Lkotlin/jvm/functions/Function1;)V
public static final fun table (Lmatchers/content/ContentMatcherBuilder;Lkotlin/jvm/functions/Function1;)V
}
diff --git a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt b/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
index 08442536..13780718 100644
--- a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
+++ b/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
@@ -3,6 +3,7 @@ package matchers.content
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
+import assertk.assertions.isNotNull
import org.jetbrains.dokka.model.withDescendants
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.test.tools.matchers.content.*
@@ -70,6 +71,23 @@ fun ContentMatcherBuilder<*>.skipAllNotMatching() {
// Convenience functions:
fun ContentMatcherBuilder<*>.group(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) = composite(block)
+fun ContentMatcherBuilder<*>.tabbedGroup(
+ block: ContentMatcherBuilder<ContentGroup>.() -> Unit
+) = composite<ContentGroup> {
+ block()
+ check { assertThat(this::style).transform { style -> style.contains(ContentStyle.TabbedContent) }.isEqualTo(true) }
+}
+
+fun ContentMatcherBuilder<*>.tab(
+ tabbedContentType: TabbedContentType, block: ContentMatcherBuilder<ContentGroup>.() -> Unit
+) = composite<ContentGroup> {
+ block()
+ check {
+ assertThat(this::extra).transform { extra -> extra[TabbedContentTypeExtra]?.value }
+ .isEqualTo(tabbedContentType)
+ }
+}
+
fun ContentMatcherBuilder<*>.header(expectedLevel: Int? = null, block: ContentMatcherBuilder<ContentHeader>.() -> Unit) =
composite<ContentHeader> {
block()
diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt
index 73ab35d4..adc51cfc 100644
--- a/core/src/main/kotlin/model/Documentable.kt
+++ b/core/src/main/kotlin/model/Documentable.kt
@@ -519,4 +519,4 @@ interface DocumentableSource {
val path: String
}
-data class TypeConstructorWithKind(val typeConstructor: TypeConstructor, val kind: ClassKind)
+data class TypeConstructorWithKind(val typeConstructor: TypeConstructor, val kind: ClassKind) \ No newline at end of file
diff --git a/core/src/main/kotlin/model/documentableUtils.kt b/core/src/main/kotlin/model/documentableUtils.kt
index e32605ca..076ca23a 100644
--- a/core/src/main/kotlin/model/documentableUtils.kt
+++ b/core/src/main/kotlin/model/documentableUtils.kt
@@ -19,3 +19,5 @@ fun DTypeParameter.filter(filteredSet: Set<DokkaSourceSet>) =
extra
)
}
+
+fun Documentable.isExtension() = this is Callable && receiver != null \ No newline at end of file
diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt
index 3c6fa5ac..78760044 100644
--- a/core/src/main/kotlin/pages/ContentNodes.kt
+++ b/core/src/main/kotlin/pages/ContentNodes.kt
@@ -392,7 +392,14 @@ enum class TextStyle : Style {
}
enum class ContentStyle : Style {
- RowTitle, TabbedContent, WithExtraAttributes, RunnableSample, InDocumentationAnchor, Caption,
+ RowTitle,
+ /**
+ * The style is used only for HTML. It is applied only for [ContentGroup].
+ * Creating and rendering tabs is a part of a renderer.
+ */
+ TabbedContent,
+
+ WithExtraAttributes, RunnableSample, InDocumentationAnchor, Caption,
Wrapped, Indented, KDocTag, Footnote
}
diff --git a/core/src/main/kotlin/pages/contentNodeProperties.kt b/core/src/main/kotlin/pages/contentNodeProperties.kt
index cfd7f769..3c9bd422 100644
--- a/core/src/main/kotlin/pages/contentNodeProperties.kt
+++ b/core/src/main/kotlin/pages/contentNodeProperties.kt
@@ -6,9 +6,23 @@ class SimpleAttr(val extraKey: String, val extraValue: String) : ExtraProperty<C
data class SimpleAttrKey(val key: String) : ExtraProperty.Key<ContentNode, SimpleAttr>
override val key: ExtraProperty.Key<ContentNode, SimpleAttr> = SimpleAttrKey(extraKey)
- companion object {
- fun header(value: String) = SimpleAttr("data-togglable", value)
- }
+}
+
+enum class BasicTabbedContentType : TabbedContentType {
+ TYPE, CONSTRUCTOR, FUNCTION, PROPERTY, ENTRY, EXTENSION_PROPERTY, EXTENSION_FUNCTION
+}
+
+/**
+ * It is used only to mark content for tabs in HTML format
+ */
+interface TabbedContentType
+
+/**
+ * @see TabbedContentType
+ */
+class TabbedContentTypeExtra(val value: TabbedContentType) : ExtraProperty<ContentNode> {
+ companion object : ExtraProperty.Key<ContentNode, TabbedContentTypeExtra>
+ override val key: ExtraProperty.Key<ContentNode, TabbedContentTypeExtra> = TabbedContentTypeExtra
}
object HtmlContent : ExtraProperty<ContentNode>, ExtraProperty.Key<ContentNode, HtmlContent> {
diff --git a/plugins/base/api/base.api b/plugins/base/api/base.api
index f529b0ee..5e36f375 100644
--- a/plugins/base/api/base.api
+++ b/plugins/base/api/base.api
@@ -10,7 +10,6 @@ public final class org/jetbrains/dokka/base/DokkaBase : org/jetbrains/dokka/plug
public final fun getDefaultExternalDocumentablesProvider ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDefaultKotlinAnalysis ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDefaultSamplesTransformer ()Lorg/jetbrains/dokka/plugability/Extension;
- public final fun getDefaultTabSortingStrategy ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDeprecatedDocumentableFilter ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDescriptorToDocumentableTranslator ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDocTagToContentConverter ()Lorg/jetbrains/dokka/plugability/Extension;
@@ -272,11 +271,6 @@ public final class org/jetbrains/dokka/base/renderers/DefaultRendererKt {
public static final fun sourceSets (Lorg/jetbrains/dokka/pages/ContentPage;)Ljava/util/Set;
}
-public final class org/jetbrains/dokka/base/renderers/DefaultTabSortingStrategy : org/jetbrains/dokka/base/renderers/TabSortingStrategy {
- public fun <init> ()V
- public fun sort (Ljava/util/Collection;)Ljava/util/List;
-}
-
public final class org/jetbrains/dokka/base/renderers/FileWriter : org/jetbrains/dokka/base/renderers/OutputWriter {
public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
@@ -1450,16 +1444,19 @@ public class org/jetbrains/dokka/base/translators/documentables/DefaultPageCreat
public synthetic fun <init> (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected fun contentForBrief (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/Documentable;)V
protected fun contentForClasslikesAndEntries (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup;
+ protected fun contentForConstructors (Ljava/util/List;Ljava/util/Set;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForDescription (Lorg/jetbrains/dokka/model/Documentable;)Ljava/util/List;
+ protected fun contentForEntries (Ljava/util/List;Ljava/util/Set;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForFunction (Lorg/jetbrains/dokka/model/DFunction;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForMember (Lorg/jetbrains/dokka/model/Documentable;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForMembers (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForModule (Lorg/jetbrains/dokka/model/DModule;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForPackage (Lorg/jetbrains/dokka/model/DPackage;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForProperty (Lorg/jetbrains/dokka/model/DProperty;)Lorg/jetbrains/dokka/pages/ContentGroup;
- protected fun contentForScope (Ljava/util/Set;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup;
- protected fun contentForScope (Lorg/jetbrains/dokka/model/WithScope;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup;
- protected fun contentForScopes (Ljava/util/List;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup;
+ protected fun contentForScope (Lorg/jetbrains/dokka/model/WithScope;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup;
+ public static synthetic fun contentForScope$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/model/WithScope;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/dokka/pages/ContentGroup;
+ protected fun contentForScopes (Ljava/util/List;Ljava/util/Set;Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup;
+ public static synthetic fun contentForScopes$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Ljava/util/List;Ljava/util/Set;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun divergentBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)V
public static synthetic fun divergentBlock$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)V
protected fun getContentBuilder ()Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder;
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index 456a587b..f76eef63 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -54,6 +54,7 @@ class DokkaBase : DokkaPlugin() {
val outputWriter by extensionPoint<OutputWriter>()
val htmlPreprocessors by extensionPoint<PageTransformer>()
val kotlinAnalysis by extensionPoint<KotlinAnalysis>()
+ @Deprecated("It is not used anymore")
val tabSortingStrategy by extensionPoint<TabSortingStrategy>()
val immediateHtmlCommandConsumer by extensionPoint<ImmediateHtmlCommandConsumer>()
val externalDocumentablesProvider by extensionPoint<ExternalDocumentablesProvider>()
@@ -182,10 +183,6 @@ class DokkaBase : DokkaPlugin() {
}
}
- val defaultTabSortingStrategy by extending {
- tabSortingStrategy with DefaultTabSortingStrategy()
- }
-
val htmlRenderer by extending {
CoreExtensions.renderer providing ::HtmlRenderer
}
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt b/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt
deleted file mode 100644
index 056e0f93..00000000
--- a/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.pages.ContentKind
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.Kind
-
-private val kindsOrder = listOf(
- ContentKind.Classlikes,
- ContentKind.Constructors,
- ContentKind.Functions,
- ContentKind.Properties,
- ContentKind.Extensions,
- ContentKind.Parameters,
- ContentKind.Inheritors,
- ContentKind.Source,
- ContentKind.Sample,
- ContentKind.Comment
-)
-
-class DefaultTabSortingStrategy : TabSortingStrategy {
- override fun <T: ContentNode> sort(tabs: Collection<T>): List<T> {
- val tabMap: Map<Kind, MutableList<T>> = kindsOrder.asSequence().map { it to mutableListOf<T>() }.toMap()
- val unrecognized: MutableList<T> = mutableListOf()
- tabs.forEach {
- tabMap[it.dci.kind]?.add(it) ?: unrecognized.add(it)
- }
- return tabMap.values.flatten() + unrecognized
- }
-
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
index b4d98b58..dfefbad8 100644
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
@@ -14,9 +14,11 @@ import org.jetbrains.dokka.base.renderers.html.innerTemplating.HtmlTemplater
import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
import org.jetbrains.dokka.base.resolvers.local.DokkaBaseLocationProvider
import org.jetbrains.dokka.base.templating.*
+import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions
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.dokka.pages.HtmlContent
import org.jetbrains.dokka.plugability.*
@@ -24,6 +26,7 @@ import org.jetbrains.dokka.utilities.htmlEscape
import org.jetbrains.kotlin.utils.addIfNotNull
internal const val TEMPLATE_REPLACEMENT: String = "###"
+internal const val TOGGLEABLE_CONTENT_TYPE_ATTR = "data-togglable"
open class HtmlRenderer(
context: DokkaContext
@@ -45,19 +48,102 @@ open class HtmlRenderer(
override val preprocessors = context.plugin<DokkaBase>().query { htmlPreprocessors }
- private val tabSortingStrategy = context.plugin<DokkaBase>().querySingle { tabSortingStrategy }
+ /**
+ * Tabs themselves are created in HTML plugin since, currently, only HTML format supports them.
+ * [TabbedContentType] is used to mark content that should be inside tab content.
+ * A tab can display multiple [TabbedContentType].
+ * The content style [ContentStyle.TabbedContent] is used to determine where tabs will be generated.
+ *
+ * @see TabbedContentType
+ * @see ContentStyle.TabbedContent
+ */
+ private fun createTabs(pageContext: ContentPage): List<ContentTab> {
+ return when(pageContext) {
+ is ClasslikePage -> createTabsForClasslikes(pageContext)
+ is PackagePage -> createTabsForPackage(pageContext)
+ else -> throw IllegalArgumentException("Page ${pageContext.name} cannot have tabs")
+ }
+ }
+
+ private fun createTabsForClasslikes(page: ClasslikePage): List<ContentTab> {
+ val documentables = page.documentables
+ fun List<Documentable>.shouldDocumentConstructors() = !this.any { it is DAnnotation }
+ val csEnum = documentables.filterIsInstance<DEnum>()
+ val csWithConstructor = documentables.filterIsInstance<WithConstructors>()
+ val scopes = documentables.filterIsInstance<WithScope>()
+ val constructorsToDocumented = csWithConstructor.flatMap { it.constructors }
+
+ val containsRenderableConstructors = constructorsToDocumented.isNotEmpty() && documentables.shouldDocumentConstructors()
+ val containsRenderableMembers =
+ containsRenderableConstructors || scopes.any { it.classlikes.isNotEmpty() || it.functions.isNotEmpty() || it.properties.isNotEmpty() }
+
+ @Suppress("UNCHECKED_CAST")
+ val extensions = (documentables as List<WithExtraProperties<DClasslike>>).flatMap {
+ it.extra[CallableExtensions]?.extensions
+ ?.filterIsInstance<Documentable>().orEmpty()
+ }
+ .distinctBy { it.sourceSets to it.dri } // [Documentable] has expensive equals/hashCode at the moment, see #2620
+ return listOfNotNull(
+ if(!containsRenderableMembers) null else
+ ContentTab(
+ "Members",
+ listOf(
+ BasicTabbedContentType.CONSTRUCTOR,
+ BasicTabbedContentType.TYPE,
+ BasicTabbedContentType.FUNCTION,
+ BasicTabbedContentType.PROPERTY
+ )
+ ),
+ if (extensions.isEmpty()) null else ContentTab(
+ "Members & Extensions",
+ listOf(
+ BasicTabbedContentType.CONSTRUCTOR,
+ BasicTabbedContentType.TYPE,
+ BasicTabbedContentType.FUNCTION,
+ BasicTabbedContentType.PROPERTY,
+ BasicTabbedContentType.EXTENSION_PROPERTY,
+ BasicTabbedContentType.EXTENSION_FUNCTION
+ )
+ ),
+ if(csEnum.isEmpty()) null else ContentTab(
+ "Entries",
+ listOf(
+ BasicTabbedContentType.ENTRY
+ )
+ )
+ )
+ }
+
+ private fun createTabsForPackage(page: PackagePage): List<ContentTab> {
+ val p = page.documentables.single() as DPackage
+ return listOfNotNull(
+ ContentTab(
+ "Types",
+ listOf(
+ BasicTabbedContentType.TYPE,
+ )
+ ),
+ if (p.functions.isEmpty()) null else ContentTab(
+ "Functions",
+ listOf(
+ BasicTabbedContentType.FUNCTION,
+ BasicTabbedContentType.EXTENSION_FUNCTION,
+ )
+ ),
+ if (p.properties.isEmpty()) null else ContentTab(
+ "Properties",
+ listOf(
+ BasicTabbedContentType.PROPERTY,
+ BasicTabbedContentType.EXTENSION_PROPERTY,
+ )
+ )
+ )
+ }
private fun <R> TagConsumer<R>.prepareForTemplates() =
if (context.configuration.delayTemplateSubstitution || this is ImmediateResolutionTagConsumer) this
else ImmediateResolutionTagConsumer(this, context)
- private fun <T : ContentNode> sortTabs(strategy: TabSortingStrategy, tabs: Collection<T>): List<T> {
- val sorted = strategy.sort(tabs)
- if (sorted.size != tabs.size)
- context.logger.warn("Tab sorting strategy has changed number of tabs from ${tabs.size} to ${sorted.size}")
- return sorted
- }
-
override fun FlowContent.wrapGroup(
node: ContentGroup,
pageContext: ContentPage,
@@ -66,20 +152,16 @@ open class HtmlRenderer(
val additionalClasses = node.style.joinToString(" ") { it.toString().toLowerCase() }
return when {
node.hasStyle(ContentStyle.TabbedContent) -> div(additionalClasses) {
- val secondLevel = node.children.filterIsInstance<ContentComposite>().flatMap { it.children }
- .filterIsInstance<ContentHeader>().flatMap { it.children }.filterIsInstance<ContentText>()
- val firstLevel = node.children.filterIsInstance<ContentHeader>().flatMap { it.children }
- .filterIsInstance<ContentText>()
-
- val renderable = sortTabs(tabSortingStrategy, firstLevel.union(secondLevel))
+ val contentTabs = createTabs(pageContext)
div(classes = "tabs-section") {
attributes["tabs-section"] = "tabs-section"
- renderable.forEachIndexed { index, node ->
+ contentTabs.forEachIndexed { index, contentTab ->
button(classes = "section-tab") {
if (index == 0) attributes["data-active"] = ""
- attributes["data-togglable"] = node.text
- text(node.text)
+ attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] =
+ contentTab.tabbedContentTypes.joinToString(",") { it.toHtmlAttribute() }
+ text(contentTab.text)
}
}
}
@@ -104,7 +186,9 @@ open class HtmlRenderer(
span("breakable-word") { childrenCallback() }
}
node.hasStyle(TextStyle.Span) -> span { childrenCallback() }
- node.dci.kind == ContentKind.Symbol -> div("symbol $additionalClasses") { childrenCallback() }
+ node.dci.kind == ContentKind.Symbol -> div("symbol $additionalClasses") {
+ childrenCallback()
+ }
node.dci.kind == SymbolContentKind.Parameters -> {
span("parameters $additionalClasses") {
childrenCallback()
@@ -122,7 +206,9 @@ open class HtmlRenderer(
}
node.dci.kind == ContentKind.Deprecation -> div("deprecation-content") { childrenCallback() }
node.hasStyle(TextStyle.Paragraph) -> p(additionalClasses) { childrenCallback() }
- node.hasStyle(TextStyle.Block) -> div(additionalClasses) { childrenCallback() }
+ node.hasStyle(TextStyle.Block) -> div(additionalClasses) {
+ childrenCallback()
+ }
node.hasStyle(TextStyle.Quotation) -> blockQuote(additionalClasses) { childrenCallback() }
node.hasStyle(TextStyle.FloatingRight) -> span("clearfix") { span("floating-right") { childrenCallback() } }
node.hasStyle(TextStyle.Strikethrough) -> strike { childrenCallback() }
@@ -139,6 +225,10 @@ open class HtmlRenderer(
node.hasStyle(ListStyle.DescriptionDetails) -> DD(emptyMap(), consumer).visit {
this@wrapGroup.childrenCallback()
}
+ node.extra.extraTabbedContentType() != null -> div() {
+ node.extra.extraTabbedContentType()?.let { attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] = it.value.toHtmlAttribute() }
+ this@wrapGroup.childrenCallback()
+ }
else -> childrenCallback()
}
}
@@ -433,6 +523,7 @@ open class HtmlRenderer(
) {
buildAnchor(contextNode)
div(classes = "table-row") {
+ contextNode.extra.extraTabbedContentType()?.let { attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] = it.value.toHtmlAttribute() }
addSourceSetFilteringAttributes(contextNode)
div("main-subrow keyValue " + contextNode.style.joinToString(separator = " ")) {
buildRowHeaderLink(toRender, pageContext, sourceSetRestriction, contextNode.anchor)
@@ -786,11 +877,19 @@ open class HtmlRenderer(
content(this, page)
}
+ private fun PageNode.getDocumentableType(): String? =
+ when(this) {
+ is PackagePage -> "package"
+ is ClasslikePage -> "classlike"
+ is MemberPage -> "member"
+ else -> null
+ }
open fun buildHtml(page: PageNode, resources: List<String>, content: FlowContent.() -> Unit): String =
templater.renderFromTemplate(DokkaTemplateTypes.BASE) {
val generatedContent =
createHTML().div("main-content") {
+ page.getDocumentableType()?.let { attributes["data-page-type"] = it }
id = "content"
(page as? ContentPage)?.let {
attributes["pageIds"] = "${context.configuration.moduleName}::${page.pageId}"
@@ -851,6 +950,28 @@ open class HtmlRenderer(
private val isPartial = context.configuration.delayTemplateSubstitution
}
+private fun TabbedContentType.toHtmlAttribute(): String =
+ when(this) {
+ is BasicTabbedContentType ->
+ when(this) {
+ BasicTabbedContentType.ENTRY -> "ENTRY"
+ BasicTabbedContentType.TYPE -> "TYPE"
+ BasicTabbedContentType.CONSTRUCTOR -> "CONSTRUCTOR"
+ BasicTabbedContentType.FUNCTION -> "FUNCTION"
+ BasicTabbedContentType.PROPERTY -> "PROPERTY"
+ BasicTabbedContentType.EXTENSION_PROPERTY -> "EXTENSION_PROPERTY"
+ BasicTabbedContentType.EXTENSION_FUNCTION -> "EXTENSION_FUNCTION"
+ }
+ else -> throw IllegalStateException("Unknown TabbedContentType $this")
+ }
+
+/**
+ * Tabs for a content with [ContentStyle.TabbedContent].
+ *
+ * @see ContentStyle.TabbedContent]
+ */
+private data class ContentTab(val text: String, val tabbedContentTypes: List<TabbedContentType>)
+
fun List<SimpleAttr>.joinAttr() = joinToString(" ") { it.extraKey + "=" + it.extraValue }
private fun String.stripDiv() = drop(5).dropLast(6) // TODO: Find a way to do it without arbitrary trims
@@ -859,6 +980,7 @@ private val PageNode.isNavigable: Boolean
get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
private fun PropertyContainer<ContentNode>.extraHtmlAttributes() = allOfType<SimpleAttr>()
+private fun PropertyContainer<ContentNode>.extraTabbedContentType() = this[TabbedContentTypeExtra]
private val ContentNode.sourceSetsFilters: String
get() = sourceSets.sourceSetIDs.joinToString(" ") { it.toString() }
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/p