Skip to content

Commit 43d2ae8

Browse files
authored
chore: refactor trimNavigationFiles task to use Gradle Worker API to improve performance (#1715)
1 parent 4f784be commit 43d2ae8

File tree

2 files changed

+96
-58
lines changed

2 files changed

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

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)