mirror of
https://github.com/apple/pkl.git
synced 2026-04-27 18:57:12 +02:00
Fix source links in pkldoc (#362)
Fixes an issue where source links are incorrectly URI encoded; i.e. `https%3A//github.com` instead of `https://github.com`. This was causing the browser to resolve these as relative to the enclosing page.
This commit is contained in:
@@ -179,7 +179,7 @@ internal class DocPackage(val docPackageInfo: DocPackageInfo, val modules: List<
|
||||
mod,
|
||||
docPackageInfo.version,
|
||||
docPackageInfo.getModuleImportUri(mod.moduleName),
|
||||
docPackageInfo.getModuleSourceCode(mod.moduleName)?.toEncodedUri(),
|
||||
docPackageInfo.getModuleSourceCode(mod.moduleName),
|
||||
exampleModulesBySubject[mod.moduleName] ?: listOf()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -160,19 +160,15 @@ data class DocPackageInfo(
|
||||
when (importUri) {
|
||||
"pkl:/" -> "pkl:${moduleName.substring(4)}".toUri()
|
||||
else -> {
|
||||
val path =
|
||||
getModulePath(moduleName, moduleNamePrefix)
|
||||
.split("/")
|
||||
.map { it.uriEncoded }
|
||||
.joinToString("/") { it } + ".pkl"
|
||||
val path = getModulePath(moduleName, moduleNamePrefix).uriEncoded + ".pkl"
|
||||
URI(importUri).resolve(path)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getModuleSourceCode(moduleName: String): String? {
|
||||
val path = "/" + getModulePath(moduleName, moduleNamePrefix) + ".pkl"
|
||||
internal fun getModuleSourceCode(moduleName: String): URI? {
|
||||
val path = "/" + getModulePath(moduleName, moduleNamePrefix).uriEncoded + ".pkl"
|
||||
// assumption: the fragment is only used for line numbers
|
||||
return sourceCodeUrlScheme?.replace("%{path}", path)?.substringBefore('#')
|
||||
return sourceCodeUrlScheme?.replace("%{path}", path)?.substringBefore('#')?.let(URI::create)
|
||||
}
|
||||
|
||||
/** Information about a depended-on package. */
|
||||
|
||||
@@ -253,7 +253,7 @@ internal class PackageScope(
|
||||
private val moduleScopes: Map<String, ModuleScope> by lazy {
|
||||
modules.associate { module ->
|
||||
val docUrl =
|
||||
url.resolve(getModulePath(module.moduleName, modulePrefix).uriEncodedPath + "/index.html")
|
||||
url.resolve(getModulePath(module.moduleName, modulePrefix).uriEncoded + "/index.html")
|
||||
module.moduleName to ModuleScope(module, docUrl, this)
|
||||
}
|
||||
}
|
||||
@@ -326,7 +326,7 @@ internal class ModuleScope(
|
||||
get() = module.moduleName
|
||||
|
||||
val path: String by lazy {
|
||||
getModulePath(module.moduleName, parent!!.docPackageInfo.moduleNamePrefix).uriEncodedPath
|
||||
getModulePath(module.moduleName, parent!!.docPackageInfo.moduleNamePrefix).uriEncoded
|
||||
}
|
||||
|
||||
override val dataUrl: URI by lazy { parent!!.dataUrl.resolve("./$path/index.js") }
|
||||
@@ -386,11 +386,12 @@ internal class ClassScope(
|
||||
) : PageScope() {
|
||||
override val url: URI by lazy {
|
||||
// `isModuleClass` distinction is relevant when this scope is a link target
|
||||
if (clazz.isModuleClass) parentUrl else parentUrl.resolve("${clazz.simpleName.uriEncoded}.html")
|
||||
if (clazz.isModuleClass) parentUrl
|
||||
else parentUrl.resolve("${clazz.simpleName.uriEncodedComponent}.html")
|
||||
}
|
||||
|
||||
override val dataUrl: URI by lazy {
|
||||
parent!!.dataUrl.resolve("${clazz.simpleName.uriEncoded}.js")
|
||||
parent!!.dataUrl.resolve("${clazz.simpleName.uriEncodedComponent}.js")
|
||||
}
|
||||
|
||||
override fun getMethod(name: String): MethodScope? =
|
||||
|
||||
@@ -426,7 +426,7 @@ internal abstract class PageGenerator<out S>(
|
||||
// anchors, and requires no JS
|
||||
protected fun HtmlBlockTag.renderAnchor(anchorId: String, cssClass: String = "anchor") {
|
||||
div {
|
||||
id = anchorId.uriEncoded
|
||||
id = anchorId.uriEncodedComponent
|
||||
classes = setOf(cssClass)
|
||||
+" " // needs some content to be considered a valid anchor by browsers
|
||||
}
|
||||
@@ -457,7 +457,7 @@ internal abstract class PageGenerator<out S>(
|
||||
protected fun HtmlBlockTag.renderSelfLink(memberName: String) {
|
||||
a {
|
||||
classes = setOf("member-selflink", "material-icons")
|
||||
href = "#${memberName.uriEncoded}"
|
||||
href = "#${memberName.uriEncodedComponent}"
|
||||
+"link"
|
||||
}
|
||||
}
|
||||
@@ -600,7 +600,8 @@ internal abstract class PageGenerator<out S>(
|
||||
for (example in examples) {
|
||||
if (first) first = false else +", "
|
||||
a {
|
||||
href = docModule.parent.docPackageInfo.getModuleSourceCode(example.moduleName)!!
|
||||
href =
|
||||
docModule.parent.docPackageInfo.getModuleSourceCode(example.moduleName)!!.toString()
|
||||
+example.shortModuleName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,12 @@ internal fun String.replaceSourceCodePlaceholders(
|
||||
.replace("%{endLine}", sourceLocation.endLine.toString())
|
||||
}
|
||||
|
||||
internal val String.uriEncoded
|
||||
/**
|
||||
* Encodes a URI string, encoding characters that are part of URI syntax.
|
||||
*
|
||||
* Follows `encodeURIComponent` from ECMAScript.
|
||||
*/
|
||||
internal val String.uriEncodedComponent
|
||||
get(): String {
|
||||
val ret = URLEncoder.encode(this, StandardCharsets.UTF_8)
|
||||
// Replace `+` with `%20` to be safe
|
||||
@@ -128,13 +133,18 @@ internal val String.uriEncoded
|
||||
return ret.replace("+", "%20")
|
||||
}
|
||||
|
||||
internal val String.uriEncodedPath
|
||||
get(): String = split("/").map { it.uriEncoded }.joinToString("/") { it }
|
||||
/**
|
||||
* Encodes a URI string, preserving characters that are part of URI syntax.
|
||||
*
|
||||
* Follows `encodeURI` from ECMAScript.
|
||||
*/
|
||||
internal val String.uriEncoded
|
||||
get(): String = replace(Regex("([^;/?:@&=+\$,#]+)")) { it.value.uriEncodedComponent }
|
||||
|
||||
fun getModulePath(moduleName: String, packagePrefix: String): String =
|
||||
moduleName.substring(packagePrefix.length).replace('.', '/')
|
||||
|
||||
internal fun String.toEncodedUri(): URI = URI(uriEncodedPath)
|
||||
internal fun String.toEncodedUri(): URI = URI(uriEncoded)
|
||||
|
||||
/**
|
||||
* Turns `"foo.bar.baz-biz"` into ``"foo.bar.`baz-biz`"``.
|
||||
|
||||
Reference in New Issue
Block a user