From 1ba42c4ac87adda5eb3af0f2fcdaa95fb45864fb Mon Sep 17 00:00:00 2001 From: Enno <458526+ennru@users.noreply.github.com> Date: Tue, 3 Dec 2019 14:43:02 +0100 Subject: [PATCH] Scaladoc: better support for inner classes (#397) * Scaladoc: better support for inner classes * Review fix --- .../paradox/markdown/Directive.scala | 21 +++++++++++++++---- .../markdown/ScaladocDirectiveSpec.scala | 11 ++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala b/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala index d6a1b4d4..96f03c69 100644 --- a/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala +++ b/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala @@ -291,7 +291,8 @@ abstract class ApiDocDirective(name: String) if (path.endsWith("$")) path.substring(0, path.length - 1) else if (path.endsWith(".package")) path.substring(0, path.length - ".package".length) else if (path.endsWith(".index")) path.substring(0, path.length - ".index".length) - else path + // for inner-class notation with $$ + else path.replaceAll("\\$\\$", ".") } catch { case e @ Url.Error(reason) => ctx.logger.debug(e) @@ -308,6 +309,11 @@ abstract class ApiDocDirective(name: String) } +object ApiDocDirective { + /** This relies on the naming convention of packages being all-lowercase (which is rarely broken). */ + def packageDotsToSlash(s: String) = s.replaceAll("(\\b[a-z]+)\\.", "$1/") +} + case class ScaladocDirective(ctx: Writer.Context) extends ApiDocDirective("scaladoc") { @@ -315,9 +321,15 @@ case class ScaladocDirective(ctx: Writer.Context) val levels = link.split("[.]") val packages = (1 to levels.init.size).map(levels.take(_).mkString(".")) val baseUrl = packages.reverse.collectFirst(baseUrls).getOrElse(defaultBaseUrl).resolve() + url(link, baseUrl) + } + + private def classDotsToDollarDollar(s: String) = s.replaceAll("(\\b[A-Z].+)\\.", "$1\\$\\$") + + private def url(link: String, baseUrl: Url): Url = { val url = Url(link).base - val path = url.getPath.replace('.', '/') + ".html" - (baseUrl / path) withFragment (url.getFragment) + val path = classDotsToDollarDollar(ApiDocDirective.packageDotsToSlash(url.getPath)) + ".html" + (baseUrl / path).withFragment(url.getFragment) } } @@ -337,7 +349,7 @@ object JavadocDirective { private[markdown] def url(link: String, baseUrl: Url, linkStyle: LinkStyle): Url = { val url = Url(link).base - val path = url.getPath.replaceAll("(\\b[a-z]+)\\.", "$1/") + ".html" + val path = ApiDocDirective.packageDotsToSlash(url.getPath) + ".html" linkStyle match { case LinkStyleFrames => baseUrl.withEndingSlash.withQuery(path).withFragment(url.getFragment) case LinkStyleDirect => (baseUrl / path).withFragment(url.getFragment) @@ -702,6 +714,7 @@ case class DependencyDirective(ctx: Writer.Context) extends LeafBlockDirective(" val startDelimiter = node.attributes.value("start-delimiter", "$") val stopDelimiter = node.attributes.value("stop-delimiter", "$") + def coordinate(name: String): Option[String] = Option(node.attributes.value(name)).map { value => variables.foldLeft(value) { diff --git a/tests/src/test/scala/com/lightbend/paradox/markdown/ScaladocDirectiveSpec.scala b/tests/src/test/scala/com/lightbend/paradox/markdown/ScaladocDirectiveSpec.scala index cc9d0542..4123f6bd 100644 --- a/tests/src/test/scala/com/lightbend/paradox/markdown/ScaladocDirectiveSpec.scala +++ b/tests/src/test/scala/com/lightbend/paradox/markdown/ScaladocDirectiveSpec.scala @@ -25,6 +25,7 @@ class ScaladocDirectiveSpec extends MarkdownBaseSpec { "scaladoc.scala.base_url" -> "http://www.scala-lang.org/api/2.11.12/", "scaladoc.akka.base_url" -> "http://doc.akka.io/api/akka/2.4.10", "scaladoc.akka.http.base_url" -> "http://doc.akka.io/api/akka-http/10.0.0", + "scaladoc.akka.kafka.base_url" -> "https://doc.akka.io/api/alpakka-kafka/current", "scaladoc.root.relative.base_url" -> ".../scaladoc/api/", "scaladoc.broken.base_url" -> "https://c|" ) @@ -62,6 +63,16 @@ class ScaladocDirectiveSpec extends MarkdownBaseSpec { html("""

Actor

""") } + it should "handle inner classes correctly" in { + markdown("@scaladoc[Consumer.Control](akka.kafka.scaladsl.Consumer.Control)") shouldEqual + html("""

Consumer.Control

""") + } + + it should "handle inner classes in $$ notation" in { + markdown("@scaladoc[Consumer.Control](akka.kafka.scaladsl.Consumer$$Control)") shouldEqual + html("""

Consumer.Control

""") + } + it should "retain whitespace before or after" in { markdown("The @scaladoc:[Model](org.example.Model) class") shouldEqual html("""

The Model class

""")