Skip to content

Commit 5f0ecad

Browse files
docs: fix broken external and internal links in Groovydocs
1 parent 5d885bf commit 5f0ecad

6 files changed

Lines changed: 647 additions & 465 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.grails.doc.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.tasks.InputDirectory
6+
import org.gradle.api.tasks.TaskAction
7+
import java.nio.file.*
8+
import java.util.regex.Matcher
9+
import java.util.regex.Pattern
10+
11+
/**
12+
* A task that repairs malformed navigation links in generated Groovydocs.
13+
* Specifically targets 'phantom' links and relative path issues in navigation files
14+
* like overview-summary.html, deprecated-list.html, and help-doc.html.
15+
*/
16+
abstract class FixGroovydocLinksTask extends DefaultTask {
17+
18+
@InputDirectory
19+
abstract DirectoryProperty getApiDocsDir()
20+
21+
@TaskAction
22+
void fixLinks() {
23+
File apiDir = apiDocsDir.get().asFile
24+
if (!apiDir.exists()) {
25+
logger.warn "API documentation directory does not exist: ${apiDir.absolutePath}"
26+
return
27+
}
28+
29+
// Patterns common to Groovydoc navigation failures
30+
Map<Pattern, String> replacements = [
31+
(Pattern.compile(/href='([^']+?)\/deprecated-list\.html'/)): "href='deprecated-list.html'",
32+
(Pattern.compile(/href='([^']+?)\/help-doc\.html'/)): "href='help-doc.html'",
33+
(Pattern.compile(/href='([^']+?)\/index-all\.html'/)): "href='index-all.html'",
34+
(Pattern.compile(/href='([^']+?)\/overview-summary\.html'/)): "href='overview-summary.html'"
35+
]
36+
37+
apiDir.eachFileRecurse { File file ->
38+
if (file.name.endsWith(".html")) {
39+
String content = file.text
40+
boolean changed = false
41+
42+
replacements.each { pattern, replacement ->
43+
Matcher matcher = pattern.matcher(content)
44+
if (matcher.find()) {
45+
content = matcher.replaceAll(replacement)
46+
changed = true
47+
}
48+
}
49+
50+
// Fix specific inner class path issues like Query/Order.Direction.html -> Query.Order.Direction.html
51+
// We only do this if the file actually exists
52+
Pattern innerClassPattern = Pattern.compile(/href='([^']+?)\/([A-Z][A-Za-z0-9_]*?)\/([A-Z][A-Za-z0-9_.]*?\.html)'/)
53+
Matcher innerMatcher = innerClassPattern.matcher(content)
54+
while (innerMatcher.find()) {
55+
String relPath = innerMatcher.group(1)
56+
String outer = innerMatcher.group(2)
57+
String inner = innerMatcher.group(3)
58+
59+
Path currentPath = file.toPath().parent
60+
Path targetPath = currentPath.resolve(relPath).resolve("${outer}.${inner}").normalize()
61+
62+
if (Files.exists(targetPath)) {
63+
String newHref = "href='${relPath}/${outer}.${inner}'"
64+
content = content.replace(innerMatcher.group(0), newHref)
65+
changed = true
66+
}
67+
}
68+
69+
if (changed) {
70+
file.text = content
71+
}
72+
}
73+
}
74+
75+
logger.lifecycle "Groovydoc link repair completed for ${apiDir.absolutePath}"
76+
}
77+
}

gradle/docs-dependencies.gradle

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,10 @@ dependencies {
3131
}
3232

3333
String resolveProjectVersion(String artifact) {
34-
String version = configurations.runtimeClasspath
35-
.resolvedConfiguration
36-
.resolvedArtifacts
37-
.find {
38-
it.moduleVersion.id.name == artifact
39-
}?.moduleVersion?.id?.version
40-
if (!version) {
41-
return null
34+
def component = configurations.runtimeClasspath.incoming.resolutionResult.allComponents.find {
35+
it.moduleVersion?.name == artifact
4236
}
43-
version
37+
return component?.moduleVersion?.version
4438
}
4539

4640
def configureGroovyDoc = tasks.register('configureGroovyDoc') {
@@ -56,12 +50,35 @@ def configureGroovyDoc = tasks.register('configureGroovyDoc') {
5650
}
5751
def springVersion = resolveProjectVersion('spring-core')
5852
if (springVersion) {
59-
links << [packages: 'org.springframework.core.', href: "https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/"]
53+
links << [packages: 'org.springframework.', href: "https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/"]
6054
}
6155
def springBootVersion = resolveProjectVersion('spring-boot')
6256
if (springBootVersion) {
6357
links << [packages: 'org.springframework.boot.', href: "https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/"]
6458
}
59+
def hibernateVersion = resolveProjectVersion('hibernate-core')
60+
if (hibernateVersion) {
61+
def shortVersion = hibernateVersion.split('\\.').take(2).join('.')
62+
links << [packages: 'org.hibernate.', href: "https://docs.jboss.org/hibernate/orm/${shortVersion}/javadocs/"]
63+
}
64+
def jakartaValidationVersion = resolveProjectVersion('jakarta.validation-api')
65+
if (jakartaValidationVersion) {
66+
links << [packages: 'jakarta.validation.', href: "https://jakarta.ee/specifications/bean-validation/3.0/apidocs/"]
67+
}
68+
def jakartaPersistenceVersion = resolveProjectVersion('jakarta.persistence-api')
69+
if (jakartaPersistenceVersion) {
70+
links << [packages: 'jakarta.persistence.', href: "https://jakarta.ee/specifications/persistence/3.1/apidocs/"]
71+
}
72+
def jakartaServletVersion = resolveProjectVersion('jakarta.servlet-api')
73+
if (jakartaServletVersion) {
74+
links << [packages: 'jakarta.servlet.', href: "https://jakarta.ee/specifications/platform/10/apidocs/"]
75+
}
76+
links << [packages: 'org.grails.datastore.', href: "https://gorm.grails.org/latest/api/"]
77+
links << [packages: 'grails.gorm.', href: "https://gorm.grails.org/latest/api/"]
78+
links << [packages: 'org.grails.gorm.', href: "https://gorm.grails.org/latest/api/"]
79+
links << [packages: 'groovy.', href: "https://docs.groovy-lang.org/latest/html/gapi/"]
80+
links << [packages: 'org.apache.groovy.', href: "https://docs.groovy-lang.org/latest/html/gapi/"]
81+
links << [packages: 'org.codehaus.groovy.', href: "https://docs.groovy-lang.org/latest/html/gapi/"]
6582
if (it.ext.has('groovydocLinks')) {
6683
links.addAll(it.ext.groovydocLinks as List<Map<String, String>>)
6784
}

0 commit comments

Comments
 (0)