diff --git a/.scala-steward.conf b/.scala-steward.conf new file mode 100644 index 00000000..aeb233b6 --- /dev/null +++ b/.scala-steward.conf @@ -0,0 +1,3 @@ +pullRequests.frequency = "@monthly" + +commits.message = "bump: ${artifactName} ${nextVersion} (was ${currentVersion})" diff --git a/RELEASING.md b/RELEASING.md index 591fdb4e..5d9f532a 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,6 +1,6 @@ # Releasing -1. Wait until all running [Travis CI jobs](https://travis-ci.com/github/lightbend/paradox/builds) complete, if any. +1. Wait until all running [GitHub Continuous Integration workflow](https://github.com/lightbend/paradox/actions/workflows/ci.yml) is complete, if any. 1. Publish the [draft release](https://github.com/lightbend/paradox/releases) with a 'v0.x.y' tag -1. Travis CI will start a [CI build](https://travis-ci.org/lightbend/paradox/builds) for the new tag and publish artifacts to Bintray and Sonatype. +1. Have someone bake the release... 1. Announce the new release in the [lightbend/paradox](https://gitter.im/lightbend/paradox) Gitter channel. 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 9e24ff47..3ebc10ea 100644 --- a/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala +++ b/core/src/main/scala/com/lightbend/paradox/markdown/Directive.scala @@ -1056,6 +1056,107 @@ case class DependencyDirective(ctx: Writer.Context) extends LeafBlockDirective(" def dotted(symbol: String): String = symbol.replaceAll("(.)([A-Z])", "$1.$2").toLowerCase } +/** + * Repository directive. + */ +case class RepositoryDirective(ctx: Writer.Context) extends LeafBlockDirective("repository") { + val variables: Map[String, String] = ctx.properties + + def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = + node.contentsNode.getChildren.asScala.headOption match { + case Some(text: TextNode) => renderRepository(text.getText, node, printer) + case _ => node.contentsNode.accept(visitor) + } + + def renderRepository(tools: String, node: DirectiveNode, printer: Printer): Unit = { + val classes = Seq("repository", node.attributes.classesString).filter(_.nonEmpty) + + val startDelimiter = node.attributes.value("start-delimiter", "$") + val stopDelimiter = node.attributes.value("stop-delimiter", "$") + + val postfixes = node.attributes + .keys() + .asScala + .toSeq + .filter(_.startsWith("name")) + .sorted + .map(_.replace("name", "")) + + def coordinate(name: String): Option[String] = + Option(node.attributes.value(name)).map { value => + variables.foldLeft(value) { case (str, (key, value)) => + str.replace(startDelimiter + key + stopDelimiter, value) + } + } + + def requiredCoordinate(name: String): String = + coordinate(name).getOrElse { + ctx.error(s"'$name' is not defined", node) + "" + } + + printer.print(s"""
""") + tools.split("[,]").map(_.trim).filter(_.nonEmpty).foreach { tool => + val (lang, code) = tool match { + case "sbt" => + val repos = postfixes.map { p => + val name = requiredCoordinate(s"name$p") + val url = requiredCoordinate(s"url$p") + s""""$name".at("$url")""" + } + + val repoStrings = repos match { + case Seq(r) => s"repositories += $r\n" + case rs => + Seq("repositories ++= Seq(\n", rs.map(a => s" $a").mkString(",\n"), "\n)\n").mkString + } + + ("scala", repoStrings) + + case "gradle" | "Gradle" => + val repos = postfixes.map { p => + val url = requiredCoordinate(s"url$p") + s""" maven { + | url "$url" + | }\n""".stripMargin + } + + ( + "gradle", + "repositories {\n mavenCentral()\n" + + repos.mkString + + "}\n" + ) + + case "maven" | "Maven" | "mvn" => + val artifacts = postfixes.map { dp => + val id = requiredCoordinate(s"id$dp") + val name = requiredCoordinate(s"name$dp") + val url = requiredCoordinate(s"url$dp") + s""" <repository> + | <id>$id</id> + | <name>$name</name> + | <url>$url</url> + | </repository>\n""".stripMargin + } + + ( + "xml", + "<project>\n ...\n <repositories>\n" + + artifacts.mkString + + " </repositories>\n</project>\n" + ) + } + printer.print(s"""
$tool
""") + printer.print(s"""
""") + printer.print(s"""
$code
""") + printer.print(s"""
""") + } + printer.print("""
""") + } + +} + case class IncludeDirective(ctx: Writer.Context) extends LeafBlockDirective("include") with SourceDirective { override def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = diff --git a/core/src/main/scala/com/lightbend/paradox/markdown/Writer.scala b/core/src/main/scala/com/lightbend/paradox/markdown/Writer.scala index d39a600f..e36df44b 100644 --- a/core/src/main/scala/com/lightbend/paradox/markdown/Writer.scala +++ b/core/src/main/scala/com/lightbend/paradox/markdown/Writer.scala @@ -158,6 +158,7 @@ object Writer { _ => InlineWrapDirective("span"), (context: Context) => InlineGroupDirective(context.groups.values.flatten.map(_.toLowerCase).toSeq), DependencyDirective.apply, + RepositoryDirective.apply, IncludeDirective.apply ) diff --git a/docs/src/main/paradox/directives/index.md b/docs/src/main/paradox/directives/index.md index c426e8c3..1380233c 100644 --- a/docs/src/main/paradox/directives/index.md +++ b/docs/src/main/paradox/directives/index.md @@ -13,6 +13,7 @@ More directives are available via @ref[extensions](../customization/extensions.m * [Index and Table Of Contents Directives](organizing-pages.md) * [Linking Directives](linking.md) * [dependencies](dependencies.md) + * [repositories](repositories.md) * [Snippet Directives](snippets.md) * [Include Directives](includes.md) * [Fiddle Directives](fiddles.md) diff --git a/docs/src/main/paradox/directives/repositories.md b/docs/src/main/paradox/directives/repositories.md new file mode 100644 index 00000000..d43f94d1 --- /dev/null +++ b/docs/src/main/paradox/directives/repositories.md @@ -0,0 +1,21 @@ +Library repositories +-------------------- + +The `@@repository` block is used to show example code for how to configure a +library repository in a build tool, such as sbt. + +```markdown +@@repository[sbt,Maven,Gradle] { + id="company-repo" + name="Company repository" + url="http://jars.acme.com" +} +``` + +Which will render as: + +@@repository[sbt,Maven,Gradle] { + id="company-repo" + name="Company repository" + url="http://jars.acme.com" +} diff --git a/tests/src/test/scala/com/lightbend/paradox/markdown/RepositoryDirectiveSpec.scala b/tests/src/test/scala/com/lightbend/paradox/markdown/RepositoryDirectiveSpec.scala new file mode 100644 index 00000000..5f074d7a --- /dev/null +++ b/tests/src/test/scala/com/lightbend/paradox/markdown/RepositoryDirectiveSpec.scala @@ -0,0 +1,141 @@ +/* + * Copyright © 2015 - 2019 Lightbend, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lightbend.paradox.markdown + +import com.lightbend.paradox.tree.Tree.Location + +class RepositoryDirectiveSpec extends MarkdownBaseSpec { + + val testProperties = Map( + "project.version" -> "10.0.10", + "scala.version" -> "2.12.3", + "scala.binary.version" -> "2.12" + ) + + implicit val context: Location[Page] => Writer.Context = { loc => + writerContext(loc).copy(properties = testProperties) + } + + "Repository directive" should "render single repo" in { + markdown(""" + |@@repository[sbt,Maven,gradle] { + | id="id1" + | name="Company repository" + | url="http://jars.acme.com" + |}""") shouldEqual html(s""" + |
+ |
sbt
+ |
+ |
+      |
+      |repositories += "Company repository".at("http://jars.acme.com")
+      |
+      |
+ |
+ |
Maven
+ |
+ |
+      |
+      |<project>
+      |  ...
+      |  <repositories>
+      |    <repository>
+      |      <id>id1</id>
+      |      <name>Company repository</name>
+      |      <url>http://jars.acme.com</url>
+      |    </repository>
+      |  </repositories>
+      |</project>
+      |
+ |
+ |
gradle
+ |
+ |
+      |
+      |repositories {
+      |    mavenCentral()
+      |    maven {
+      |        url "http://jars.acme.com"
+      |    }
+      |}
+      |
+ |
+ |
""") + } + + "Repository directive" should "render two repos" in { + markdown(""" + |@@repository[sbt,Maven,gradle] { + | id1="id1" + | name1="Company repository" + | url1="http://jars.acme.com" + | id2="id-2" + | name2="Company repository 2" + | url2="http://uberjars.acme.com" + |}""") shouldEqual html(s""" + |
+ |
sbt
+ |
+ |
+         |
+         |repositories ++= Seq(
+         |  "Company repository".at("http://jars.acme.com"),
+         |  "Company repository 2".at("http://uberjars.acme.com")
+         |)
+         |
+         |
+ |
+ |
Maven
+ |
+ |
+         |
+         |<project>
+         |  ...
+         |  <repositories>
+         |    <repository>
+         |      <id>id1</id>
+         |      <name>Company repository</name>
+         |      <url>http://jars.acme.com</url>
+         |    </repository>
+         |    <repository>
+         |      <id>id-2</id>
+         |      <name>Company repository 2</name>
+         |      <url>http://uberjars.acme.com</url>
+         |    </repository>
+         |  </repositories>
+         |</project>
+         |
+ |
+ |
gradle
+ |
+ |
+         |
+         |repositories {
+         |    mavenCentral()
+         |    maven {
+         |        url "http://jars.acme.com"
+         |    }
+         |    maven {
+         |        url "http://uberjars.acme.com"
+         |    }
+         |}
+         |
+ |
+ |
""") + } + +}