aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt6
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt39
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt26
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js95
-rw-r--r--plugins/base/src/main/resources/dokka/styles/style.css33
5 files changed, 195 insertions, 4 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index a6052a9e..382b8f86 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -174,4 +174,10 @@ class DokkaBase : DokkaPlugin() {
)
} order { after(rootCreator) }
}
+
+ val sourcesetDependencyAppender by extending {
+ htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator)}
+ }
+
+
} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
index 52f7024a..b089c71a 100644
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
@@ -63,13 +63,35 @@ open class HtmlRenderer(
}
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() }
+ node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") {
+ filterButtons(node)
+ childrenCallback()
+ }
node.hasStyle(TextStyle.Paragraph) -> p(additionalClasses) { childrenCallback() }
node.hasStyle(TextStyle.Block) -> div(additionalClasses) { childrenCallback() }
else -> childrenCallback()
}
}
+ private fun FlowContent.filterButtons(group: ContentGroup) {
+ div(classes = "filter-section") {
+ id = "filter-section"
+ group.sourceSets.forEach {
+ button(classes = "platform-tag platform-selector") {
+ attributes["data-active"] = ""
+ attributes["data-filter"] = it.sourceSetName
+ when(it.platform.key){
+ "common" -> classes = classes + "common-like"
+ "native" -> classes = classes + "native-like"
+ "jvm" -> classes = classes + "jvm-like"
+ "js" -> classes = classes + "js-like"
+ }
+ text(it.sourceSetName)
+ }
+ }
+ }
+ }
+
override fun FlowContent.buildPlatformDependent(content: PlatformHintedContent, pageContext: ContentPage) =
buildPlatformDependent(content.sourceSets.map { it to setOf(content.inner) }.toMap(), pageContext, content.extra)
@@ -108,6 +130,8 @@ open class HtmlRenderer(
attributes["data-toggle-list"] = "data-toggle-list"
contents.forEachIndexed { index, pair ->
button(classes = "platform-bookmark") {
+ attributes["data-filterable-current"] = pair.first.sourceSetName
+ attributes["data-filterable-set"] = pair.first.sourceSetName
if (index == 0) attributes["data-active"] = ""
attributes["data-toggle"] = pair.first.sourceSetName
when(
@@ -160,8 +184,15 @@ open class HtmlRenderer(
consumer.onTagContentUnsafe {
+createHTML().div("divergent-group"){
+ attributes["data-filterable-current"] = groupedDivergent.keys.joinToString(" ") {
+ it.sourceSetName
+ }
+ attributes["data-filterable-set"] = groupedDivergent.keys.joinToString(" ") {
+ it.sourceSetName
+ }
consumer.onTagContentUnsafe { +it.key.first }
div("main-subrow") {
+
if (node.implicitlySourceSetHinted) {
buildPlatformDependent(
groupedDivergent.map { (sourceSet, elements) ->
@@ -242,6 +273,12 @@ open class HtmlRenderer(
?.let {
withAnchor(node.dci.dri.first().toString()) {
div(classes = "table-row") {
+ attributes["data-filterable-current"] = node.sourceSets.joinToString(" ") {
+ it.sourceSetName
+ }
+ attributes["data-filterable-set"] = node.sourceSets.joinToString(" ") {
+ it.sourceSetName
+ }
it.filterIsInstance<ContentLink>().takeIf { it.isNotEmpty() }?.let {
div("main-subrow " + node.style.joinToString(" ")) {
it.filter { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }
diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
index 710407c5..45ef1457 100644
--- a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
@@ -6,6 +6,7 @@ import kotlinx.html.table
import kotlinx.html.tbody
import org.jetbrains.dokka.base.renderers.platforms
import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.pages.PageTransformer
@@ -66,8 +67,33 @@ object StyleAndScriptsAppender : PageTransformer {
"styles/style.css",
"scripts/navigationLoader.js",
"scripts/platformContentHandler.js",
+ "scripts/sourceset_dependencies.js",
"styles/jetbrains-mono.css"
)
)
}
+}
+
+class SourcesetDependencyAppender(val context: DokkaContext) : PageTransformer{
+ override fun invoke(input: RootPageNode): RootPageNode {
+ val dependenciesMap = context.configuration.passesConfigurations.map {
+ it.sourceSetName to it.dependentSourceSets
+ }.toMap()
+ fun createDependenciesJson() : String = "sourceset_dependencies = '{${
+ dependenciesMap.entries.joinToString(", ") {
+ "\"${it.key}\": [${it.value.joinToString(","){
+ "\"$it\""
+ }}]"
+ }
+ }}'"
+ val deps = RendererSpecificResourcePage(
+ name = "scripts/sourceset_dependencies.js",
+ children = emptyList(),
+ strategy = RenderingStrategy.Write(createDependenciesJson())
+ )
+
+ return input.modified(
+ children = input.children + deps
+ )
+ }
} \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js b/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js
index 72c8daae..cd993587 100644
--- a/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js
+++ b/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js
@@ -1,13 +1,71 @@
+filteringContext = {
+ dependencies: {},
+ restrictedDependencies: [],
+ activeFilters: []
+}
window.addEventListener('load', () => {
+ initializeFiltering()
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)))
+ .forEach(elem => elem.addEventListener('click', (event) => toggleSections(event)))
+ document.getElementById('filter-section').addEventListener('click', (event) => filterButtonHandler(event))
document.querySelector(".tabs-section-body")
.querySelector("div[data-togglable]")
.setAttribute("data-active", "")
})
+function filterButtonHandler(event) {
+ if(event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) {
+ let sourceset = event.target.getAttribute("data-filter")
+ if(filteringContext.activeFilters.indexOf(sourceset) != -1) {
+ filterSourceset(sourceset)
+ } else {
+ unfilterSourceset(sourceset)
+ }
+ }
+ refreshFilterButtons();
+ refreshPlatformTabs()
+}
+
+function initializeFiltering() {
+ filteringContext.dependencies = JSON.parse(sourceset_dependencies)
+ document.querySelectorAll("#filter-section > button")
+ .forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter")))
+ Object.keys(filteringContext.dependencies).forEach(p => {
+ filteringContext.dependencies[p] = filteringContext.dependencies[p]
+ .filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q))
+ })
+ filteringContext.activeFilters = filteringContext.restrictedDependencies
+}
+
+function refreshFilterButtons() {
+ document.querySelectorAll("#filter-section > button")
+ .forEach(f => {
+ if(filteringContext.activeFilters.indexOf(f.getAttribute("data-filter")) != -1){
+ f.setAttribute("data-active","")
+ } else {
+ f.removeAttribute("data-active")
+ }
+ })
+}
+
+function filterSourceset(sourceset) {
+ filteringContext.activeFilters = filteringContext.activeFilters.filter(p => p != sourceset)
+ refreshFiltering()
+}
+
+function unfilterSourceset(sourceset) {
+ if(filteringContext.activeFilters.length == 0) {
+ filteringContext.activeFilters = filteringContext.dependencies[sourceset].concat([sourceset])
+ refreshFiltering()
+ } else {
+ filteringContext.activeFilters.push(sourceset)
+ refreshFiltering()
+ }
+}
+
+
function toggleSections(evt){
if(!evt.target.getAttribute("data-togglable")) return
@@ -50,3 +108,38 @@ function togglePlatformDependent(e, container) {
}
}
}
+
+function refreshFiltering() {
+ let sourcesetList = filteringContext.activeFilters
+ document.querySelectorAll("[data-filterable-set]")
+ .forEach(
+ elem => {
+ let platformList = elem.getAttribute("data-filterable-set").split(' ').filter(v => -1 !== sourcesetList.indexOf(v))
+ elem.setAttribute("data-filterable-current", platformList.join(' '))
+ }
+ )
+}
+
+function refreshPlatformTabs() {
+ document.querySelectorAll(".platform-hinted > .platform-bookmarks-row").forEach(
+ p => {
+ let active = false;
+ let firstAvailable = null
+ p.childNodes.forEach(
+ element => {
+ if(element.getAttribute("data-filterable-current") != ''){
+ if( firstAvailable == null) {
+ firstAvailable = element
+ }
+ if(element.hasAttribute("data-active")) {
+ active = true;
+ }
+ }
+ }
+ )
+ if( active == false && firstAvailable !== null ) {
+ firstAvailable.click()
+ }
+ }
+ )
+}
diff --git a/plugins/base/src/main/resources/dokka/styles/style.css b/plugins/base/src/main/resources/dokka/styles/style.css
index 671dfe8a..d9927046 100644
--- a/plugins/base/src/main/resources/dokka/styles/style.css
+++ b/plugins/base/src/main/resources/dokka/styles/style.css
@@ -62,6 +62,11 @@
padding: 24px 0
}
+.cover {
+ display: flex;
+ flex-direction: column;
+}
+
.tabbedcontent {
padding: 24px 0;
}
@@ -483,9 +488,11 @@ footer {
display: flex;
flex-direction: row;
padding: 4px 8px;
- height: 16px;
+ height: 24px;
border-radius: 100px;
-
+ box-sizing: border-box;
+ border: 1px solid transparent;
+ margin: 2px;
font-family: Inter, Arial, sans-serif;
font-size: 12px;
font-weight: 400;
@@ -494,6 +501,7 @@ footer {
line-height: normal;
letter-spacing: normal;
text-align: center;
+ outline: none;
color: #fff
@@ -528,6 +536,27 @@ footer {
color: white;
}
+.filter-section {
+ display: flex;
+ display: flex;
+ flex-direction: row;
+ align-self: flex-end;
+ min-height: 30px;
+}
+
+.platform-selector:hover {
+ border: 1px solid #A6AFBA !important;
+}
+
+[data-filterable-current=''] {
+ display: none !important;
+}
+.platform-selector:not([data-active]) {
+ border: 1px solid #DADFE6;
+ background-color: white;
+ color: #637282;
+}
+
td.content {
padding-left: 24px;
padding-top: 16px;