Skip to content

Commit 5873abe

Browse files
committed
chore: refactor trimNavigationFiles task to use Gradle Worker API to improve performance
1 parent ad23744 commit 5873abe

File tree

2 files changed

+91
-58
lines changed

2 files changed

+91
-58
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package aws.sdk.kotlin.dokka
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.logging.Logger
6+
import org.gradle.api.tasks.InputDirectory
7+
import org.gradle.api.tasks.TaskAction
8+
import org.gradle.workers.WorkAction
9+
import org.gradle.workers.WorkParameters
10+
import org.gradle.workers.WorkerExecutor
11+
import org.jsoup.Jsoup
12+
import java.io.File
13+
import javax.inject.Inject
14+
15+
abstract class TrimNavigation @Inject constructor(private val workerExecutor: WorkerExecutor) : DefaultTask() {
16+
@get:InputDirectory
17+
abstract val sourceDirectory: DirectoryProperty
18+
19+
init {
20+
description = "Trims navigation.html files to remove unrelated projects' side menus"
21+
group = "documentation"
22+
}
23+
24+
@TaskAction
25+
fun trimNavigation() {
26+
val queue = workerExecutor.noIsolation()
27+
28+
sourceDirectory
29+
.asFileTree
30+
.filter { it.isDirectory() && it.resolve("navigation.html").exists() }
31+
.forEach { dir ->
32+
queue.submit(TrimModule::class.java) {
33+
moduleDirectory = dir
34+
logger = this@TrimNavigation.logger
35+
projectRoot = project.layout.projectDirectory.asFile
36+
}
37+
}
38+
}
39+
}
40+
41+
interface TrimModuleParameters : WorkParameters {
42+
var logger: Logger
43+
var moduleDirectory: File
44+
var projectRoot: File
45+
}
46+
47+
abstract class TrimModule : WorkAction<TrimModuleParameters> {
48+
override fun execute() {
49+
val moduleDirectory = parameters.moduleDirectory
50+
val moduleName = moduleDirectory.name
51+
val navigation = moduleDirectory.resolve("navigation.html")
52+
53+
val logger = parameters.logger
54+
val relativePath = navigation.toRelativeString(parameters.projectRoot)
55+
logger.info("Trimming $relativePath...")
56+
57+
val doc = Jsoup.parse(navigation)
58+
59+
// Remove all parent directory elements from all navigation links
60+
doc.select("a[href^=../]").forEach { anchor ->
61+
var href = anchor.attr("href")
62+
63+
while (href.startsWith("../")) {
64+
href = href.removePrefix("../")
65+
}
66+
67+
anchor.attr("href", href)
68+
}
69+
70+
// Trim side menus
71+
doc.select("div.sideMenu > div.toc--part")
72+
.filterNot { it.id().startsWith("$moduleName-nav-submenu") }
73+
.forEach { moduleMenu ->
74+
val moduleRow = moduleMenu.select("div.toc--row").first()!!
75+
val toggleButton = moduleRow.select("button.toc--button").single()
76+
toggleButton.remove()
77+
78+
moduleMenu.children()
79+
.filterNot { it == moduleRow }
80+
.forEach { it.remove() }
81+
}
82+
83+
// Update navigation.html
84+
val trimmedSideMenuParts = doc.select("div.sideMenu > div.toc--part")
85+
navigation.writeText("<div class=\"sideMenu\">\n$trimmedSideMenuParts\n</div>")
86+
}
87+
}

buildSrc/src/main/kotlin/dokka-convention.gradle.kts

Lines changed: 4 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import org.jsoup.Jsoup
7-
import kotlin.io.path.ExperimentalPathApi
8-
import kotlin.io.path.PathWalkOption
9-
import kotlin.io.path.exists
10-
import kotlin.io.path.isDirectory
11-
import kotlin.io.path.name
12-
import kotlin.io.path.walk
6+
import aws.sdk.kotlin.dokka.TrimNavigation
137

148
plugins {
159
id("org.jetbrains.dokka")
@@ -80,58 +74,10 @@ dependencies {
8074
dokkaPlugin(project(":dokka-aws"))
8175
}
8276

83-
tasks.register("trimNavigationFiles") {
84-
description = "Trims navigation.html files to remove unrelated projects' side menus"
85-
group = "documentation"
86-
87-
doLast {
88-
val dokkaOutputDir = layout.buildDirectory.get().dir("dokka/html").asFile.toPath()
89-
90-
if (!dokkaOutputDir.exists()) {
91-
logger.info("Dokka output directory not found at ${dokkaOutputDir.toAbsolutePath()}, skipping navigation trimming")
92-
return@doLast
93-
}
94-
95-
@OptIn(ExperimentalPathApi::class)
96-
dokkaOutputDir.walk(PathWalkOption.INCLUDE_DIRECTORIES)
97-
.filter { it.isDirectory() && it.resolve("navigation.html").exists() }
98-
.forEach { moduleDir ->
99-
val moduleName = moduleDir.name
100-
101-
val navigation = moduleDir.resolve("navigation.html").toFile()
102-
val doc = Jsoup.parse(navigation)
103-
104-
// Remove all parent directory elements from all navigation links
105-
doc.select("a[href^=../]").forEach { anchor ->
106-
var href = anchor.attr("href")
107-
108-
while (href.startsWith("../")) {
109-
href = href.removePrefix("../")
110-
}
111-
112-
anchor.attr("href", href)
113-
}
114-
115-
// Trim side menus
116-
doc.select("div.sideMenu > div.toc--part")
117-
.filterNot { it.id().startsWith("$moduleName-nav-submenu") }
118-
.forEach { moduleMenu ->
119-
val moduleRow = moduleMenu.select("div.toc--row").first()!!
120-
val toggleButton = moduleRow.select("button.toc--button").single()
121-
toggleButton.remove()
122-
123-
moduleMenu.children()
124-
.filterNot { it == moduleRow }
125-
.forEach { it.remove() }
126-
}
127-
128-
// Update navigation.html
129-
val trimmedSideMenuParts = doc.select("div.sideMenu > div.toc--part")
130-
navigation.writeText("<div class=\"sideMenu\">\n$trimmedSideMenuParts\n</div>")
131-
}
132-
}
77+
val trimNavigationTask = tasks.register<TrimNavigation>("trimNavigationFiles") {
78+
sourceDirectory.set(layout.buildDirectory.get().dir("dokka/html"))
13379
}
13480

13581
tasks.dokkaGenerate {
136-
finalizedBy("trimNavigationFiles")
82+
finalizedBy(trimNavigationTask)
13783
}

0 commit comments

Comments
 (0)