diff options
12 files changed, 368 insertions, 151 deletions
diff --git a/core/.gitignore b/core/.gitignore index a259cd26..afd3caa6 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -1,2 +1,3 @@ src/main/resources/dokka/scripts/main.js -src/main/resources/dokka/scripts/main.js.map
\ No newline at end of file +src/main/resources/dokka/scripts/main.js.map +src/main/resources/dokka/scripts/*.svg
\ No newline at end of file diff --git a/core/search-component/src/main/js/search/app-root.js b/core/search-component/src/main/js/search/app-root.js index 25a374a5..5d650581 100644 --- a/core/search-component/src/main/js/search/app-root.js +++ b/core/search-component/src/main/js/search/app-root.js @@ -1,13 +1,47 @@ -import React, {Component} from 'react'; +import React, {useRef, useState, useEffect} from 'react'; import {WithFuzzySearchFilter} from './search'; import './app.css'; -export default class AppRoot extends Component { - render() { - return ( - <div className="search-content"> - <WithFuzzySearchFilter/> - </div> - ); - } +function useComponentVisible(initialIsVisible) { + const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible); + const ref = useRef(null); + + const handleHideDropdown = (event) => { + if (event.key === "Escape") { + setIsComponentVisible(false); + } + }; + + const handleClickOutside = event => { + if (ref.current && !ref.current.contains(event.target)) { + setIsComponentVisible(false); + } + }; + + useEffect(() => { + document.addEventListener("keydown", handleHideDropdown, true); + document.addEventListener("click", handleClickOutside, true); + return () => { + document.removeEventListener("keydown", handleHideDropdown, true); + document.removeEventListener("click", handleClickOutside, true); + }; + }); + + return { ref, isComponentVisible, setIsComponentVisible }; +} + +export const AppRoot = () => { + const { + ref, + isComponentVisible, + setIsComponentVisible + } = useComponentVisible(false); + + return <div ref={ref} className="search-content"> + {isComponentVisible && (<WithFuzzySearchFilter/>)} + {!isComponentVisible && ( + <span onClick={() => setIsComponentVisible(true)}> + <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path d="M19.64 18.36l-6.24-6.24a7.52 7.52 0 1 0-1.28 1.28l6.24 6.24zM7.5 13.4a5.9 5.9 0 1 1 5.9-5.9 5.91 5.91 0 0 1-5.9 5.9z"/></svg> + </span>)} + </div> }
\ No newline at end of file diff --git a/core/search-component/src/main/js/search/app.css b/core/search-component/src/main/js/search/app.css index 933237e0..c51d3fe1 100644 --- a/core/search-component/src/main/js/search/app.css +++ b/core/search-component/src/main/js/search/app.css @@ -17,5 +17,5 @@ html, } .search-content { - margin: calc(var(--ring-unit) * 4); + padding: 24px 41px; } diff --git a/core/search-component/src/main/js/search/app.js b/core/search-component/src/main/js/search/app.js index 64091607..bceffa48 100644 --- a/core/search-component/src/main/js/search/app.js +++ b/core/search-component/src/main/js/search/app.js @@ -2,7 +2,7 @@ import React from 'react'; import {render} from 'react-dom'; import RedBox from 'redbox-react'; -import AppRoot from './app-root'; +import {AppRoot} from './app-root'; import './app.css'; const appEl = document.getElementById('searchBar'); diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt index 8e1d01a7..2a668e09 100644 --- a/core/src/main/kotlin/pages/ContentNodes.kt +++ b/core/src/main/kotlin/pages/ContentNodes.kt @@ -221,7 +221,7 @@ enum class TextStyle : Style { } enum class ContentStyle : Style { - RowTitle + RowTitle, TabbedContent, TabbedContentBody, WithExtraAttributes } object CommentTable: Style diff --git a/core/src/main/kotlin/pages/contentNodeProperties.kt b/core/src/main/kotlin/pages/contentNodeProperties.kt index 9eabcd12..67acef6d 100644 --- a/core/src/main/kotlin/pages/contentNodeProperties.kt +++ b/core/src/main/kotlin/pages/contentNodeProperties.kt @@ -5,4 +5,8 @@ import org.jetbrains.dokka.model.properties.ExtraProperty class SimpleAttr(val extraKey: String, val extraValue: String) : ExtraProperty<ContentNode> { 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) + } } diff --git a/core/src/main/resources/dokka/scripts/navigationLoader.js b/core/src/main/resources/dokka/scripts/navigationLoader.js index b30a866d..cac46d2a 100644 --- a/core/src/main/resources/dokka/scripts/navigationLoader.js +++ b/core/src/main/resources/dokka/scripts/navigationLoader.js @@ -6,7 +6,6 @@ window.addEventListener('load', () => { }).then(() => { document.querySelectorAll(".overview > a").forEach(link => { link.setAttribute("href", pathToRoot + link.getAttribute("href")); - console.log(link.attributes["href"]) }) }).then(() => { document.querySelectorAll(".sideMenuPart").forEach(nav => { diff --git a/core/src/main/resources/dokka/scripts/platformContentHandler.js b/core/src/main/resources/dokka/scripts/platformContentHandler.js index b4a9e7c9..72c8daae 100644 --- a/core/src/main/resources/dokka/scripts/platformContentHandler.js +++ b/core/src/main/resources/dokka/scripts/platformContentHandler.js @@ -1,8 +1,31 @@ window.addEventListener('load', () => { document.querySelectorAll("div[data-platform-hinted]") .forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event,elem))) + document.querySelectorAll("div[tabs-section]") + .forEach(elem => elem.addEventListener('click', (event) => toggleSections(event))) + document.querySelector(".tabs-section-body") + .querySelector("div[data-togglable]") + .setAttribute("data-active", "") +}) + +function toggleSections(evt){ + if(!evt.target.getAttribute("data-togglable")) return + + const activateTabs = (containerClass) => { + for(const element of document.getElementsByClassName(containerClass)){ + for(const child of element.children){ + if(child.getAttribute("data-togglable") === evt.target.getAttribute("data-togglable")){ + child.setAttribute("data-active", "") + } else { + child.removeAttribute("data-active") + } + } + } } -) + + activateTabs("tabs-section") + activateTabs("tabs-section-body") +} function togglePlatformDependent(e, container) { let target = e.target diff --git a/core/src/main/resources/dokka/styles/style.css b/core/src/main/resources/dokka/styles/style.css index ef936fcf..f2e10811 100644 --- a/core/src/main/resources/dokka/styles/style.css +++ b/core/src/main/resources/dokka/styles/style.css @@ -2,6 +2,84 @@ @import url('https://rsms.me/inter/inter.css'); @import url('jetbrains-mono.css'); +:root { + --breadcrumb-font-color: #A6AFBA; + --hover-link-color: #5B5DEF +} + +#content { + padding: 0 41px; +} + +.breadcrumbs { + padding: 24px 0; + color: var(--breadcrumb-font-color); +} + +.breadcrumbs a { + color: var(--breadcrumb-font-color) +} + +.breadcrumbs a:hover { + color: var(--hover-link-color) +} + +.tabs-section-body > *:not([data-active]){ + display: none; +} + +.tabs-section > .section-tab:first-child { + margin-left: 0; +} + +.section-tab { + border: 0; + cursor: pointer; + background-color: transparent; + border-bottom: 1px solid #DADFE6; + padding: 11px 3px; + font-size: 14px; + color: #637282; + outline:none; + margin: 0 8px; +} + +.section-tab:hover { + color: #282E34; + border-bottom: 2px solid var(--hover-link-color); +} + +.section-tab[data-active=''] { + color: #282E34; + border-bottom: 2px solid var(--hover-link-color); +} + +.tabs-section-body { + padding: 24px 0 +} + +.cover > .platform-hinted { + padding: 24px 0 +} + +.tabbedcontent { + padding: 24px 0; +} + +.cover .platform-hinted .single-content > .symbol { + background-color: white; +} + +.divergent-group { + background-color: white; + padding: 12px 8px; + margin-bottom: 2px; +} + +.divergent-group .table-row { + background-color: #F4F4F4; +} + #container { display: flex; flex-direction: row; @@ -204,7 +282,7 @@ td:first-child { } .symbol > a { - color: #5B5DEF; + color: var(--hover-link-color); text-decoration: underline; } @@ -217,7 +295,7 @@ td:first-child { .brief { white-space: pre-wrap; overflow: hidden; - padding-top: 24px; + padding-top: 8px; } h1, h2, h3, h4, h5, h6 { @@ -233,7 +311,9 @@ h1, h2, h3 { } h1 { - font-size: 28px; + font-size: 60px; + line-height: 64px; + letter-spacing: -1.5px; } h2 { @@ -470,7 +550,7 @@ td.content { } .main-subrow > a:hover { - color: #5B5DEF; + color: var(--hover-link-color); } .platform-hinted { @@ -541,7 +621,7 @@ td.content { .sideMenuPart[data-active] > .overview { background: rgba(91, 93, 239, 0.15); - border-left: 4px solid #5B5DEF; + border-left: 4px solid var(--hover-link-color); } .table { @@ -553,7 +633,7 @@ td.content { display: flex; flex-direction: column; background: white; - margin: 10px; + margin-bottom: 2px; padding: 16px 24px 16px 24px; } diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index c62c5d3c..792eb1dc 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -7,6 +7,7 @@ import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.renderers.DefaultRenderer import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.SourceSetData +import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin @@ -36,6 +37,30 @@ 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 = 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 == ContentKind.Symbol -> div("symbol $additionalClasses") { childrenCallback() } node.dci.kind == ContentKind.BriefComment -> div("brief $additionalClasses") { childrenCallback() } node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") { childrenCallback() } @@ -46,15 +71,18 @@ open class HtmlRenderer( } override fun FlowContent.buildPlatformDependent(content: PlatformHintedContent, pageContext: ContentPage) = - buildPlatformDependent(content.sourceSets.map { it to setOf(content.inner) }.toMap(), pageContext) + buildPlatformDependent(content.sourceSets.map { it to setOf(content.inner) }.toMap(), pageContext, content.extra) private fun FlowContent.buildPlatformDependent( nodes: Map<SourceSetData, Collection<ContentNode>>, - pageContext: ContentPage + pageContext: ContentPage, + extra: PropertyContainer<ContentNode> = PropertyContainer.empty() ) { var mergedToOneSourceSet : SourceSetData? = null div("platform-hinted") { attributes["data-platform-hinted"] = "data-platform-hinted" + extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue } + val additionalClasses = if(nodes.toList().size == 1) "single-content" else "" var counter = 0 val contents = nodes.toList().map { (sourceSet, elements) -> sourceSet to createHTML(prettyPrint = false).div { @@ -66,7 +94,7 @@ open class HtmlRenderer( sourceSets.filterNot { sourceSetDependencyMap[it].orEmpty().any { dependency -> sourceSets.contains(dependency) } }.map { - it to createHTML(prettyPrint = false).div(classes = "content") { + it to createHTML(prettyPrint = false).div(classes = "content $additionalClasses") { if (counter++ == 0) attributes["data-active"] = "" attributes["data-togglable"] = it.sourceSetName unsafe { @@ -130,27 +158,29 @@ open class HtmlRenderer( distinct.forEach { val groupedDivergent = it.value.groupBy { it.second } - consumer.onTagContentUnsafe { +it.key.first } consumer.onTagContentUnsafe { - +createHTML(prettyPrint = false).div("main-subrow") { - if (node.implicitlySourceSetHinted) { - buildPlatformDependent( - groupedDivergent.map { (sourceSet, elements) -> - sourceSet to elements.map { e -> e.first.divergent } - }.toMap(), - pageContext - ) - if (distinct.size > 1 && groupedDivergent.size == 1) { - createPlatformTags(node, groupedDivergent.keys) - } - } else { - it.value.forEach { - buildContentNode(it.first.divergent, pageContext, setOf(it.second)) + +createHTML().div("divergent-group"){ + consumer.onTagContentUnsafe { +it.key.first } + div("main-subrow") { + if (node.implicitlySourceSetHinted) { + buildPlatformDependent( + groupedDivergent.map { (sourceSet, elements) -> + sourceSet to elements.map { e -> e.first.divergent } + }.toMap(), + pageContext + ) + if (distinct.size > 1 && groupedDivergent.size == 1) { + createPlatformTags(node, groupedDivergent.keys) + } + } else { + it.value.forEach { + buildContentNode(it.first.divergent, pageContext, setOf(it.second)) + } } } + consumer.onTagContentUnsafe { +it.key.second } } } - consumer.onTagContentUnsafe { +it.key.second } } } @@ -273,6 +303,7 @@ open class HtmlRenderer( sourceSetRestriction: Set<SourceSetData>? ) { div(classes = "table") { + node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue } node.children.forEach { buildRow(it, pageContext, sourceSetRestriction) } @@ -435,4 +466,6 @@ fun List<SimpleAttr>.joinAttr() = joinToString(" ") { it.extraKey + "=" + it.ext private fun String.stripDiv() = drop(5).dropLast(6) // TODO: Find a way to do it without arbitrary trims private val PageNode.isNavigable: Boolean - get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
\ No newline at end of file + get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing + +fun PropertyContainer<ContentNode>.extraHtmlAttributes() = allOfType<SimpleAttr>()
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt index c0b8233c..e324c5bb 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt @@ -70,7 +70,8 @@ class SourceLinksTransformer(val context: DokkaContext, val builder: PageContent }, DCI(node.dri, ContentKind.Source), node.documentable!!.sourceSets.toSet(), - style = emptySet() + style = emptySet(), + extra = mainExtra + SimpleAttr.header("Sources") ) } @@ -91,9 +92,22 @@ class SourceLinksTransformer(val context: DokkaContext, val builder: PageContent private fun ContentNode.addTable(table: ContentGroup): ContentNode = when (this) { - is ContentGroup -> copy( - children = children + table - ) + is ContentGroup -> { + if(hasTabbedContent()){ + copy( + children = children.map { + if(it.hasStyle(ContentStyle.TabbedContent) && it is ContentGroup){ + it.copy(children = it.children + table) + } else { + it + } + } + ) + } else { + copy(children = children + table) + } + + } else -> ContentGroup( children = listOf(this, table), extra = this.extra, @@ -114,4 +128,6 @@ data class SourceLink(val path: String, val url: String, val lineSuffix: String? constructor(sourceLinkDefinition: DokkaConfiguration.SourceLinkDefinition, sourceSetData: SourceSetData) : this( sourceLinkDefinition.path, sourceLinkDefinition.url, sourceLinkDefinition.lineSuffix, sourceSetData ) -}
\ No newline at end of file +} + +fun ContentGroup.hasTabbedContent(): Boolean = children.any { it.hasStyle(ContentStyle.TabbedContent) }
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt index d4ee88d8..409b0d6f 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt @@ -7,6 +7,7 @@ import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.Doc import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.doc.* +import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.model.properties.WithExtraProperties import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.utilities.DokkaLogger @@ -67,6 +68,7 @@ open class DefaultPageCreator( group(kind = ContentKind.Cover) { header(1, m.name) } + +contentForDescription(m) +contentForComments(m) block("Packages", 2, ContentKind.Packages, m.packages, m.sourceSets.toSet()) { link(it.name, it.dri) @@ -78,14 +80,17 @@ open class DefaultPageCreator( protected open fun contentForPackage(p: DPackage) = contentBuilder.contentFor(p) { group(kind = ContentKind.Cover) { header(1, "Package ${p.name}") + +contentForDescription(p) } - +contentForComments(p) - +contentForScope(p, p.dri, p.sourceSets) - block("Type aliases", 2, ContentKind.TypeAliases, p.typealiases, p.sourceSets.toSet()) { - link(it.name, it.dri, kind = ContentKind.Main) - sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint) { - +buildSignature(it) - contentForBrief(it) + group(styles = setOf(ContentStyle.TabbedContent)){ + +contentForComments(p) + +contentForScope(p, p.dri, p.sourceSets) + block("Type aliases", 2, ContentKind.TypeAliases, p.typealiases, p.sourceSets.toSet(), extra = mainExtra + SimpleAttr.header("Type aliases")) { + link(it.name, it.dri, kind = ContentKind.Main) + sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint, styles = emptySet()) { + +buildSignature(it) + contentForBrief(it) + } } } } @@ -95,9 +100,9 @@ open class DefaultPageCreator( dri: DRI, sourceSets: List<SourceSetData> ) = contentBuilder.contentFor(s as Documentable) { - divergentBlock("Types", s.classlikes, ContentKind.Classlikes) - divergentBlock("Functions", s.functions, ContentKind.Functions) - block("Properties", 2, ContentKind.Properties, s.properties, sourceSets.toSet()) { + divergentBlock("Types", s.classlikes, ContentKind.Classlikes, extra = mainExtra + SimpleAttr.header("Types")) + divergentBlock("Functions", s.functions, ContentKind.Functions, extra = mainExtra + SimpleAttr.header( "Functions")) + block("Properties", 2, ContentKind.Properties, s.properties, sourceSets.toSet(), extra = mainExtra + SimpleAttr.header( "Properties")) { link(it.name, it.dri, kind = ContentKind.Main) sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint) { +buildSignature(it) @@ -122,7 +127,8 @@ open class DefaultPageCreator( }, DCI(setOf(dri), ContentKind.Inheritors), sourceSets.toSet(), - style = emptySet() + style = emptySet(), + extra = mainExtra + SimpleAttr.header( "Inheritors") ) } } @@ -132,9 +138,12 @@ open class DefaultPageCreator( group(kind = ContentKind.Cover) { header(1, e.name) +buildSignature(e) + +contentForDescription(e) + } + group(styles = setOf(ContentStyle.TabbedContent)){ + +contentForComments(e) + +contentForScope(e, e.dri, e.sourceSets) } - +contentForComments(e) - +contentForScope(e, e.dri, e.sourceSets) } protected open fun contentForClasslike(c: DClasslike) = contentBuilder.contentFor(c) { @@ -142,36 +151,39 @@ open class DefaultPageCreator( header(1, c.name.orEmpty()) sourceSetDependentHint(c.dri, c.sourceSets.toSet()) { +buildSignature(c) + +contentForDescription(c) } } - +contentForComments(c) - - if (c is WithConstructors) { - block( - "Constructors", - 2, - ContentKind.Constructors, - c.constructors.filter { it.extra[PrimaryConstructorExtra] == null }, - c.sourceSets.toSet() - ) { - link(it.name, it.dri, kind = ContentKind.Main) - sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint) { - +buildSignature(it) - contentForBrief(it) + + group(styles = setOf(ContentStyle.TabbedContent)) { + +contentForComments(c) + if (c is WithConstructors) { + block( + "Constructors", + 2, + ContentKind.Constructors, + c.constructors.filter { it.extra[PrimaryConstructorExtra] == null }, + c.sourceSets.toSet(), + extra = PropertyContainer.empty<ContentNode>() + SimpleAttr.header("Constructors") + ) { + link(it.name, it.dri, kind = ContentKind.Main) + sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint, styles = emptySet()) { + +buildSignature(it) + contentForBrief(it) + } } } - } - if (c is DEnum) { - block("Entries", 2, ContentKind.Classlikes, c.entries, c.sourceSets.toSet()) { - link(it.name, it.dri) - sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint) { - +buildSignature(it) - contentForBrief(it) + if (c is DEnum) { + block("Entries", 2, ContentKind.Classlikes, c.entries, c.sourceSets.toSet(), extra = mainExtra + SimpleAttr.header("Entries"), styles = emptySet()) { + link(it.name, it.dri) + sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependantHint) { + +buildSignature(it) + contentForBrief(it) + } } } + +contentForScope(c, c.dri, c.sourceSets) } - - +contentForScope(c, c.dri, c.sourceSets) } @Suppress("UNCHECKED_CAST") @@ -188,16 +200,16 @@ open class DefaultPageCreator( private inline fun <reified T : TagWrapper> GroupedTags.isNotEmptyForTag(): Boolean = this[T::class]?.isNotEmpty() ?: false - protected open fun contentForComments( + protected open fun contentForDescription( d: Documentable - ): List<ContentNode> { + ): ContentNode { val tags: GroupedTags = d.documentation.flatMap { (pd, doc) -> doc.children.asSequence().map { pd to it }.toList() }.groupBy { it.second::class } val platforms = d.sourceSets - fun DocumentableContentBuilder.contentForDescription() { + return contentBuilder.contentFor(d) { val description = tags.withTypeUnnamed<Description>() if (description.any { it.value.root.children.isNotEmpty() }) { platforms.forEach { platform -> @@ -208,34 +220,60 @@ open class DefaultPageCreator( } } } + + val unnamedTags: List<SourceSetDependent<TagWrapper>> = + tags.filterNot { (k, _) -> k.isSubclassOf(NamedTagWrapper::class) || k in specialTags } + .map { (_, v) -> v.mapNotNull { (k,v) -> k?.let { it to v } }.toMap() } + platforms.forEach { platform -> + unnamedTags.forEach { pdTag -> + pdTag[platform]?.also { tag -> + group(sourceSets = setOf(platform)) { + header(4, tag.toHeaderString()) + comment(tag.root) + } + } + } + } } + } + + protected open fun contentForComments( + d: Documentable + ): List<ContentNode> { + val tags: GroupedTags = d.documentation.flatMap { (pd, doc) -> + doc.children.asSequence().map { pd to it }.toList() + }.groupBy { it.second::class } + + val platforms = d.sourceSets fun DocumentableContentBuilder.contentForParams() { if (tags.isNotEmptyForTag<Param>()) { - val receiver = tags.withTypeUnnamed<Receiver>() - val params = tags.withTypeNamed<Param>() - platforms.forEach { - header(4, "Parameters", kind = ContentKind.Parameters, platformData = setOf(it)) - } - table(kind = ContentKind.Parameters) { - platforms.flatMap { platform -> - val receiverRow = receiver[platform]?.let { - buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) { - text("<receiver>", styles = mainStyles + ContentStyle.RowTitle) - comment(it.root) - } - } + header(2, "Parameters") + group(extra = mainExtra + SimpleAttr.header("Parameters"), styles = setOf(ContentStyle.WithExtraAttributes)){ + sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependantHint) { + val receiver = tags.withTypeUnnamed<Receiver>() + val params = tags.withTypeNamed<Param>() + table(kind = ContentKind.Parameters) { + platforms.flatMap { platform -> + val receiverRow = receiver[platform]?.let { + buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) { + text("<receiver>", styles = mainStyles + ContentStyle.RowTitle) + comment(it.root) + } + } - val paramRows = params.mapNotNull { (_, param) -> - param[platform]?.let { - buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) { - text(it.name, kind = ContentKind.Parameters, styles = mainStyles + ContentStyle.RowTitle) - comment(it.root) + val paramRows = params.mapNotNull { (_, param) -> + param[platform]?.let { + buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) { + text(it.name, kind = ContentKind.Parameters, styles = mainStyles + ContentStyle.RowTitle) + comment(it.root) + } + } } + + listOfNotNull(receiverRow) + paramRows } } - - listOfNotNull(receiverRow) + paramRows } } } @@ -243,18 +281,20 @@ open class DefaultPageCreator( fun DocumentableContentBuilder.contentForSeeAlso() { if (tags.isNotEmptyForTag<See>()) { - val seeAlsoTags = tags.withTypeNamed<See>() - platforms.forEach { - header(4, "See also", kind = ContentKind.Comment, platformData = setOf(it)) - } - table(kind = ContentKind.Sample) { - platforms.flatMap { platform -> - seeAlsoTags.mapNotNull { (_, see) -> - see[platform]?.let { - buildGroup(sourceSets = setOf(platform), kind = ContentKind.Comment, styles = mainStyles + ContentStyle.RowTitle) { - if (it.address != null) link(it.name, it.address!!, kind = ContentKind.Comment) - else text(it.name, kind = ContentKind.Comment) - comment(it.root) + header(2, "See also") + group(extra = mainExtra + SimpleAttr.header("See also"), styles = setOf(ContentStyle.WithExtraAttributes)){ + sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependantHint) { + val seeAlsoTags = tags.withTypeNamed<See>() + table(kind = ContentKind.Sample) { + platforms.flatMap { platform -> + seeAlsoTags.mapNotNull { (_, see) -> + see[platform]?.let { + buildGroup(sourceSets = setOf(platform), kind = ContentKind.Comment, styles = mainStyles + ContentStyle.RowTitle) { + if (it.address != null) link(it.name, it.address!!, kind = ContentKind.Comment) + else text(it.name, kind = ContentKind.Comment) + comment(it.root) + } + } } } } @@ -266,13 +306,17 @@ open class DefaultPageCreator( fun DocumentableContentBuilder.contentForSamples() { val samples = tags.withTypeNamed<Sample>() if (samples.isNotEmpty()) { - platforms.forEach { platformData -> - val content = samples.filter { it.value.isEmpty() || platformData in it.value } - if (content.isNotEmpty()) { - group(sourceSets = setOf(platformData)) { - header(4, "Samples", kind = ContentKind.Comment) - content.forEach { - comment(Text(it.key)) + header(2, "Samples") + group(extra = mainExtra + SimpleAttr.header("Samples"), styles = setOf(ContentStyle.WithExtraAttributes)){ + sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependantHint) { + table(kind = ContentKind.Sample) { + platforms.map { platformData -> + val content = samples.filter { it.value.isEmpty() || platformData in it.value } + buildGroup(sourceSets = setOf(platformData), styles = setOf(ContentStyle.RowTitle)) { + content.forEach { + comment(Text(it.key)) + } + } } } } @@ -280,32 +324,11 @@ open class DefaultPageCreator( } } - fun DocumentableContentBuilder.contentForUnnamedTags() { - val unnamedTags: List<SourceSetDependent<TagWrapper>> = - tags.filterNot { (k, _) -> k.isSubclassOf(NamedTagWrapper::class) || k in specialTags } - .map { (_, v) -> v.mapNotNull { (k,v) -> k?.let { it to v } }.toMap() } - platforms.forEach { platform -> - unnamedTags.forEach { pdTag -> - pdTag[platform]?.also { tag -> - group(sourceSets = setOf(platform)) { - header(4, tag.toHeaderString()) - comment(tag.root) - } - } - } - } - } - return contentBuilder.contentFor(d) { if (tags.isNotEmpty()) { - header(3, "Description") - sourceSetDependentHint(sourceSets = platforms.toSet()) { - contentForDescription() - contentForSamples() - contentForParams() - contentForUnnamedTags() - contentForSeeAlso() - } + contentForSamples() + contentForSeeAlso() + contentForParams() } }.children } @@ -323,13 +346,16 @@ open class DefaultPageCreator( protected open fun contentForFunction(f: DFunction) = contentForMember(f) protected open fun contentForTypeAlias(t: DTypeAlias) = contentForMember(t) protected open fun contentForMember(d: Documentable) = contentBuilder.contentFor(d) { - header(1, d.name.orEmpty()) + group(kind = ContentKind.Cover) { + header(1, d.name.orEmpty()) + } divergentGroup(ContentDivergentGroup.GroupID("member")) { instance(setOf(d.dri), d.sourceSets.toSet()) { divergent(kind = ContentKind.Symbol) { +buildSignature(d) } after { + +contentForDescription(d) +contentForComments(d) } } @@ -339,11 +365,12 @@ open class DefaultPageCreator( protected open fun DocumentableContentBuilder.divergentBlock( name: String, collection: Collection<Documentable>, - kind: ContentKind + kind: ContentKind, + extra: PropertyContainer<ContentNode> = mainExtra, ) { if (collection.any()) { header(2, name) - table(kind) { + table(kind, extra = extra) { collection.groupBy { it.name }.map { (elementName, elements) -> // This groupBy should probably use LocationProvider buildGroup(elements.map { it.dri }.toSet(), elements.flatMap { it.sourceSets }.toSet(), kind = kind) { link(elementName.orEmpty(), elements.first().dri, kind = kind) |