Skip to content

Commit 39b635c

Browse files
Merge pull request #14516 from jchyb/scaladoc/fix-i14505-i14504
Scaladoc: fix issues with incorrect external links and special characters
2 parents b60d90f + 213e275 commit 39b635c

File tree

9 files changed

+53
-15
lines changed

9 files changed

+53
-15
lines changed

scaladoc-js/main/src/searchbar/PageEntry.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ import scala.scalajs.js
44

55
@js.native
66
trait PageEntryJS extends js.Object {
7-
val n: String = js.native
8-
val t: String = js.native
9-
val d: String = js.native
10-
val l: String = js.native
11-
val k: String = js.native
7+
val n: String = js.native
8+
val t: String = js.native
9+
val d: String = js.native
10+
val l: String = js.native
11+
val e: Boolean = js.native
12+
val k: String = js.native
1213
}
1314

1415
case class PageEntry(
1516
fullName: String,
1617
description: String,
1718
location: String,
19+
isLocationExternal: Boolean,
1820
shortName: String,
1921
kind: String,
2022
tokens: List[String]
@@ -34,6 +36,7 @@ object PageEntry {
3436
jsObj.t,
3537
jsObj.d,
3638
jsObj.l,
39+
jsObj.e,
3740
jsObj.n.toLowerCase,
3841
jsObj.k,
3942
StringUtils.createCamelCaseTokens(jsObj.n)

scaladoc-js/main/src/searchbar/SearchbarComponent.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ class SearchbarComponent(engine: SearchbarEngine, inkuireEngine: InkuireJSSearch
2222
icon.classList.add(p.kind.take(2))
2323

2424
val resultA = document.createElement("a").asInstanceOf[html.Anchor]
25-
resultA.href = Globals.pathToRoot + p.location
25+
resultA.href =
26+
if (p.isLocationExternal) {
27+
p.location
28+
} else {
29+
Globals.pathToRoot + p.location
30+
}
2631
resultA.text = s"${p.fullName}"
2732
resultA.onclick = (event: Event) =>
2833
if (document.body.contains(rootDiv)) {
@@ -57,11 +62,14 @@ class SearchbarComponent(engine: SearchbarEngine, inkuireEngine: InkuireJSSearch
5762
icon.classList.add(m.entryType.take(2))
5863

5964
val resultA = document.createElement("a").asInstanceOf[html.Anchor]
65+
// Inkuire pageLocation should start with e (external)
66+
// or i (internal). The rest of the string is an absolute
67+
// or relative URL
6068
resultA.href =
61-
if(new URI(m.pageLocation).isAbsolute()) {
62-
m.pageLocation
69+
if (m.pageLocation(0) == 'e') {
70+
m.pageLocation.substring(1)
6371
} else {
64-
Globals.pathToRoot + m.pageLocation
72+
Globals.pathToRoot + m.pageLocation.substring(1)
6573
}
6674
resultA.text = m.functionName
6775
resultA.onclick = (event: Event) =>

scaladoc-js/main/test/dotty/tools/scaladoc/MatchersTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class MatchersTest:
3434
s"$kind $name",
3535
"",
3636
"",
37+
false,
3738
s"$name",
3839
kind,
3940
StringUtils.createCamelCaseTokens(name)

scaladoc/src/dotty/tools/scaladoc/Inkuire.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ object Inkuire {
114114
name: String,
115115
packageName: String,
116116
uri: String,
117+
isLocationExternal: Boolean,
117118
entryType: String
118119
)
119120

@@ -333,7 +334,7 @@ object Inkuire {
333334
("signature", serialize(e.signature)),
334335
("name", serialize(e.name)),
335336
("packageName", serialize(e.packageName)),
336-
("uri", serialize(e.uri)),
337+
("uri", serialize((if e.isLocationExternal then "e" else "i") + e.uri)),
337338
("entryType", serialize(e.entryType))
338339
)
339340
}

scaladoc/src/dotty/tools/scaladoc/renderers/Locations.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,12 @@ trait Locations(using ctx: DocContext):
8181

8282
def resolveRoot(dri: DRI, path: String): String = resolveRoot(rawLocation(dri), path)
8383
def absolutePath(dri: DRI, extension: String = "html"): String = rawLocation(dri).mkString("", "/", s".$extension")
84-
def absolutePathWithAnchor(dri: DRI, extension: String = "html"): String = s"${absolutePath(dri, extension)}#${dri.anchor}"
84+
85+
def escapedAbsolutePathWithAnchor(dri: DRI, extension: String = "html"): String =
86+
s"${escapeUrl(absolutePath(dri, extension))}#${dri.anchor}"
87+
88+
def relativeInternalOrAbsoluteExternalPath(dri: DRI): String =
89+
dri.externalLink.getOrElse(escapedAbsolutePathWithAnchor(dri))
8590

8691
def resolveLink(dri: DRI, url: String): String =
8792
if URI(url).isAbsolute then url else resolveRoot(dri, url)

scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ abstract class Renderer(rootPackage: Member, val members: Map[DRI, Member], prot
120120
val signatureRenderer = new SignatureRenderer:
121121
def currentDri: DRI = page.link.dri
122122
def link(dri: DRI): Option[String] =
123-
Some(pathToPage(currentDri, dri)).filter(_ != UnresolvedLocationLink)
123+
dri.externalLink.orElse(
124+
Some(pathToPage(currentDri, dri)).filter(_ != UnresolvedLocationLink)
125+
)
124126

125127
MemberRenderer(signatureRenderer).fullMember(m)
126128
case t: ResolvedTemplate => siteContent(page.link.dri, t)

scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ trait Resources(using ctx: DocContext) extends Locations, Writer:
133133
}.mkString
134134

135135
def mkEntry(dri: DRI, name: String, text: String, descr: String, kind: String) = jsonObject(
136-
"l" -> jsonString(absolutePathWithAnchor(dri)),
136+
"l" -> jsonString(relativeInternalOrAbsoluteExternalPath(dri)),
137+
"e" -> (if dri.externalLink.isDefined then rawJSON("true") else rawJSON("false")),
137138
"n" -> jsonString(name),
138139
"t" -> jsonString(text),
139140
"d" -> jsonString(descr),

scaladoc/src/dotty/tools/scaladoc/tasty/InkuireSupport.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ trait InkuireSupport(using DocContext) extends Resources:
114114
),
115115
name = name,
116116
packageName = ownerName,
117-
uri = methodSymbol.dri.externalLink.getOrElse(absolutePathWithAnchor(methodSymbol.dri)),
117+
uri = methodSymbol.dri.externalLink.getOrElse(escapedAbsolutePathWithAnchor(methodSymbol.dri)),
118+
isLocationExternal = methodSymbol.dri.externalLink.isDefined,
118119
entryType = "def"
119120
)
120121
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))
@@ -142,7 +143,8 @@ trait InkuireSupport(using DocContext) extends Resources:
142143
),
143144
name = name,
144145
packageName = ownerName,
145-
uri = valSymbol.dri.externalLink.getOrElse(absolutePathWithAnchor(valSymbol.dri)),
146+
uri = valSymbol.dri.externalLink.getOrElse(escapedAbsolutePathWithAnchor(valSymbol.dri)),
147+
isLocationExternal = valSymbol.dri.externalLink.isDefined,
146148
entryType = "val"
147149
)
148150
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))

scaladoc/test/dotty/tools/scaladoc/renderers/LocationTests.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,18 @@ class LocationTests:
3737
"../../annotation",
3838
path("api/scala/annotation/meta/beanGetter", "api/scala/annotation"),
3939
)
40+
41+
@Test
42+
def testAnchorLinks() =
43+
def pathWithAnchor(location: String, anchor: String) =
44+
locations.escapedAbsolutePathWithAnchor(new DRI(location, anchor))
45+
46+
assertEquals(
47+
"scala/%23::.html#abcde",
48+
pathWithAnchor("scala.#::", "abcde")
49+
)
50+
51+
assertEquals(
52+
"scala/collection/immutable/LazyList$$%23$.html#abcde",
53+
pathWithAnchor("scala.collection.immutable.LazyList$$#$", "abcde")
54+
)

0 commit comments

Comments
 (0)