Skip to content

Commit

Permalink
Rework homepage links:
Browse files Browse the repository at this point in the history
* no GitHub support by default
* use URL from base plugin configuration
* add integration test for the multi-module project that the homepage link exists everywhere
  • Loading branch information
whyoleg committed Oct 27, 2023
1 parent 506ef29 commit 6662802
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
}

allprojects {
tasks.withType<org.jetbrains.dokka.gradle.AbstractDokkaTask> {
pluginsMapConfiguration.set(
mapOf(
"org.jetbrains.dokka.base.DokkaBase" to """{ "homepageLink" : "https://github.com/Kotlin/dokka/tree/master/integration-tests/gradle/projects/it-multimodule-0/" }"""
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ class MultiModule0IntegrationTest : AbstractGradleIntegrationTest() {
"Expected moduleC being mentioned in -modules.html"
)

val indexHtmls = outputDir.walkTopDown().filter {
it.isFile && it.name == "index.html"
}.toList()

assertEquals(10, indexHtmls.size)

indexHtmls.forEach {
assertTrue(
it.readText().contains(
"""https://github.com/Kotlin/dokka/tree/master/integration-tests/gradle/projects/it-multimodule-0/"""
),
"File ${it.absolutePath} doesn't contain link to homepage"
)
}

val gfmOutputDir = File(projectDir, "moduleA/build/dokka/gfmMultiModule")
assertTrue(gfmOutputDir.isDirectory, "Missing dokka GFM output directory")

Expand Down
1 change: 1 addition & 0 deletions plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public data class DokkaBaseConfiguration(
var customStyleSheets: List<File> = defaultCustomStyleSheets,
var customAssets: List<File> = defaultCustomAssets,
var separateInheritedMembers: Boolean = separateInheritedMembersDefault,
var homepageLink: String? = null,
var footerMessage: String = defaultFooterMessage,
var mergeImplicitExpectActualDeclarations: Boolean = mergeImplicitExpectActualDeclarationsDefault,
var templatesDir: File? = defaultTemplatesDir
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public object AssetsInstaller : PageTransformer {
"images/copy-successful-icon.svg",
"images/theme-toggle.svg",
"images/burger.svg",
"images/github-link.svg",
"images/homepage.svg",

// navigation icons
"images/nav-icons/abstract-class.svg",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,32 +92,11 @@ public class DefaultTemplateModelFactory(
mapper["footerMessage"] =
(configuration?.footerMessage?.takeIf(String::isNotBlank) ?: DokkaBaseConfiguration.defaultFooterMessage)

calculateSourceUrlFromSourceLinks()?.let { mapper["sourceUrl"] = it }
configuration?.homepageLink?.takeIf(String::isNotBlank)?.let { mapper["homepageLink"] = it }

return mapper
}

private fun calculateSourceUrlFromSourceLinks(): String? {
fun parseGithubInfo(link: String): Pair<String, String>? {
val (
_, // entire match
owner,
repo
) = githubLinkRegex.find(link)?.groupValues ?: return null
return owner to repo
}

val (owner, repo) = context.configuration.sourceSets
.asSequence()
.flatMap { it.sourceLinks }
.map { it.remoteUrl.toString() }
.map(::parseGithubInfo)
.distinct()
.singleOrNull() ?: return null

return "https://github.com/$owner/$repo/"
}

private val DisplaySourceSet.comparableKey
get() = sourceSetIDs.merged.let { it.scopeId + it.sourceSetName }
private val String.isAbsolute: Boolean
Expand Down Expand Up @@ -155,9 +134,6 @@ public class DefaultTemplateModelFactory(
}
}

private companion object {
val githubLinkRegex = Regex("https?://github\\.com/([\\w,\\-_]+)/([\\w,\\-_]+)/.*")
}
}

private class PrintDirective(val generateData: () -> String) : TemplateDirectiveModel {
Expand Down
5 changes: 0 additions & 5 deletions plugins/base/src/main/resources/dokka/images/github-link.svg

This file was deleted.

5 changes: 5 additions & 0 deletions plugins/base/src/main/resources/dokka/images/homepage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions plugins/base/src/main/resources/dokka/styles/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -394,35 +394,35 @@ td:first-child {
}
/* /--- Navigation THEME --- */

/* --- Navigation SOURCE --- */
.navigation-controls--source {
/* --- Navigation HOMEPAGE --- */
.navigation-controls--homepage {
height: 40px;
width: 40px;
display: block;
border-radius: 50%;
cursor: pointer;
}

.navigation-controls--source a::before {
.navigation-controls--homepage a::before {
height: 100%;
width: 20px;
margin-left: 10px;
display: block;
content: "";
background: url("../images/github-link.svg");
background: url("../images/homepage.svg");
background-size: 100% 100%;
}

.navigation-controls--source:hover {
.navigation-controls--homepage:hover {
background: var(--white-10);
}

@media (max-width: 759px) {
.navigation-controls--source {
.navigation-controls--homepage {
display: none;
}
}
/* /--- Navigation SOURCE --- */
/* /--- Navigation HOMEPAGE --- */

.navigation .platform-selector:not([data-active]) {
color: #fff;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
<@source_set_selector.display/>
</div>
<div class="navigation-controls">
<#if sourceUrl?has_content>
<div class="navigation-controls--btn navigation-controls--source" id="source-link" role="button"><a href="${sourceUrl}"></a></div>
<#if homepageLink?has_content>
<div class="navigation-controls--btn navigation-controls--homepage" id="homepage-link" role="button"><a href="${homepageLink}"></a></div>
</#if>
<button class="navigation-controls--btn navigation-controls--theme" id="theme-toggle-button" type="button">switch theme</button>
<div class="navigation-controls--btn navigation-controls--search" id="searchBar" role="button">search in API</div>
Expand Down
85 changes: 26 additions & 59 deletions plugins/base/src/test/kotlin/renderers/html/HeaderTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

package renderers.html

import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.SourceLinkDefinitionImpl
import org.jetbrains.dokka.PluginConfigurationImpl
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration
import org.jetbrains.dokka.base.templating.toJsonString
import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import org.jetbrains.dokka.pages.RootPageNode
import org.jetbrains.dokka.plugability.DokkaContext
import org.jsoup.Jsoup
import utils.TestOutputWriter
import utils.TestOutputWriterPlugin
import java.net.URL
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
Expand All @@ -33,80 +36,44 @@ class HeaderTest : BaseAbstractTest() {
}

@Test
fun `should include link to github if sourceLinks are pointed to github`() {
val sourceLink = SourceLinkDefinitionImpl(
localDirectory = "",
remoteUrl = URL("https://github.com/Kotlin/dokka/tree/main"),
remoteLineSuffix = null
)
fun `should include homepage link if homepageLink is provided`() {
testRendering(
configuration.copy(
sourceSets = configuration.sourceSets.map {
it.copy(sourceLinks = setOf(sourceLink))
}
)
DokkaBaseConfiguration(homepageLink = "https://github.com/Kotlin/dokka/")
) { _, _, writer ->
val renderedContent = navigationElement(writer)

val sourceLinkElement =
assertNotNull(renderedContent.getElementById("source-link"), "Source link element not found")
assertNotNull(renderedContent.getElementById("homepage-link"), "Source link element not found")
val aElement = assertNotNull(sourceLinkElement.selectFirst("a"))
assertEquals("https://github.com/Kotlin/dokka/", aElement.attr("href"))
}
}

@Test
fun `should not include link to github if sourceLinks are different`() {
val sourceLink = SourceLinkDefinitionImpl(
localDirectory = "",
remoteUrl = URL("https://github.com/Kotlin/dokka/tree/main"),
remoteLineSuffix = null
)
testRendering(
configuration.copy(
sourceSets = listOf(
configuration.sourceSets[0].copy(sourceLinks = setOf(sourceLink)),
configuration.sourceSets[1].copy(sourceLinks = setOf(sourceLink.copy(remoteUrl = URL("https://github.com/Kotlin/dokkatoo/tree/main"))))
)
)
) { _, _, writer ->
fun `should not include homepage link by default`() {
testRendering(null) { _, _, writer ->
val renderedContent = navigationElement(writer)
assertNull(renderedContent.getElementById("source-link"), "Source link element found")
assertNull(renderedContent.getElementById("homepage-link"), "Source link element found")
}
}

@Test
fun `should not include link to github if sourceLinks are pointed to gitlab`() {
val sourceLink = SourceLinkDefinitionImpl(
localDirectory = "",
remoteUrl = URL("https://gitlab.com/Kotlin/dokka/tree/main"),
remoteLineSuffix = null
)
testRendering(
configuration.copy(
sourceSets = configuration.sourceSets.map {
it.copy(sourceLinks = setOf(sourceLink))
}
)
) { _, _, writer ->
val renderedContent = navigationElement(writer)
assertNull(renderedContent.getElementById("source-link"), "Source link element found")
}
}

@Test
fun `should not include link to github if there are no sourceLinks`() {
testRendering(configuration) { _, _, writer ->
val renderedContent = navigationElement(writer)
assertNull(renderedContent.getElementById("source-link"), "Source link element found")
}
}


private fun testRendering(
configuration: DokkaConfigurationImpl = this.configuration,
baseConfiguration: DokkaBaseConfiguration?,
block: (RootPageNode, DokkaContext, writer: TestOutputWriter) -> Unit
) {
fun configuration(): DokkaConfigurationImpl {
baseConfiguration ?: return configuration
return configuration.copy(
pluginsConfiguration = listOf(
PluginConfigurationImpl(
DokkaBase::class.java.canonicalName,
DokkaConfiguration.SerializationFormat.JSON,
toJsonString(baseConfiguration)
)
)
)
}

val writerPlugin = TestOutputWriterPlugin()
testInline(
"""
Expand All @@ -115,7 +82,7 @@ class HeaderTest : BaseAbstractTest() {
|/src/js/Test.kt
|fun test() {}
""",
configuration,
configuration(),
pluginOverrides = listOf(writerPlugin)
) {
renderingStage = { node, context ->
Expand Down

0 comments on commit 6662802

Please sign in to comment.