diff --git a/project/Build.scala b/project/Build.scala index f015bd7760f5..d7a3668a82e2 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1624,6 +1624,9 @@ object Build { "-skip-by-regex:.+\\.impl($|\\..+) " + "-comment-syntax wiki -siteroot scaladoc/scala3-docs -project-logo scaladoc/scala3-docs/logo.svg " + "-external-mappings:.*java.*::javadoc::https://docs.oracle.com/javase/8/docs/api/ " + + "-social-links:github::https://github.com/lampepfl/dotty," + + "gitter::https://gitter.im/scala/scala," + + "twitter::https://twitter.com/scala_lang " + s"-source-links:$stdLibRoot=github://scala/scala/v${stdlibVersion(Bootstrapped)}#src/library " + s"-doc-root-content $docRootFile" )) diff --git a/scaladoc-js/src/Main.scala b/scaladoc-js/src/Main.scala index 25892c5acb7e..7b32aed9a1ea 100644 --- a/scaladoc-js/src/Main.scala +++ b/scaladoc-js/src/Main.scala @@ -2,4 +2,5 @@ package dotty.tools.scaladoc object Main extends App { Searchbar() + SocialLinks() } diff --git a/scaladoc-js/src/social-links/SocialLinks.scala b/scaladoc-js/src/social-links/SocialLinks.scala new file mode 100644 index 000000000000..5fbe42eb99e7 --- /dev/null +++ b/scaladoc-js/src/social-links/SocialLinks.scala @@ -0,0 +1,12 @@ +package dotty.tools.scaladoc + +import org.scalajs.dom._ +import org.scalajs.dom.ext._ + +class SocialLinks: + def addIcon(elem: html.Element) = + val img = document.createElement("img").asInstanceOf[html.Image] + img.src = s"${Globals.pathToRoot}images/${elem.getAttribute("data-icon-path")}" + elem.appendChild(img) + + document.querySelectorAll(".social-icon").collect { case e: html.Element => e }.foreach(addIcon) diff --git a/scaladoc/README.md b/scaladoc/README.md index ad5a6c0247e5..c55a256e342d 100644 --- a/scaladoc/README.md +++ b/scaladoc/README.md @@ -167,3 +167,9 @@ Make sure all the tests pass (simply run `sbt test` to verify that). A documentation tool needs to access compiler information about the project - it needs to list all definitions, resolve them by name, and query their members. Tasty Reflect is the dedicated way in Scala 3 of accessing this information. + +## Credits + +- [Flatart](https://www.iconfinder.com/Flatart) - Gitter icon + + diff --git a/scaladoc/resources/dotty_res/images/discord-icon-black.png b/scaladoc/resources/dotty_res/images/discord-icon-black.png new file mode 100644 index 000000000000..e756933de15e Binary files /dev/null and b/scaladoc/resources/dotty_res/images/discord-icon-black.png differ diff --git a/scaladoc/resources/dotty_res/images/discord-icon-white.png b/scaladoc/resources/dotty_res/images/discord-icon-white.png new file mode 100644 index 000000000000..d5346b794c9a Binary files /dev/null and b/scaladoc/resources/dotty_res/images/discord-icon-white.png differ diff --git a/scaladoc/resources/dotty_res/images/github-icon-black.png b/scaladoc/resources/dotty_res/images/github-icon-black.png new file mode 100644 index 000000000000..8b25551a9792 Binary files /dev/null and b/scaladoc/resources/dotty_res/images/github-icon-black.png differ diff --git a/scaladoc/resources/dotty_res/images/github-icon-white.png b/scaladoc/resources/dotty_res/images/github-icon-white.png new file mode 100644 index 000000000000..628da97c7089 Binary files /dev/null and b/scaladoc/resources/dotty_res/images/github-icon-white.png differ diff --git a/scaladoc/resources/dotty_res/images/gitter-icon-black.png b/scaladoc/resources/dotty_res/images/gitter-icon-black.png new file mode 100644 index 000000000000..7751e3490adf Binary files /dev/null and b/scaladoc/resources/dotty_res/images/gitter-icon-black.png differ diff --git a/scaladoc/resources/dotty_res/images/gitter-icon-white.png b/scaladoc/resources/dotty_res/images/gitter-icon-white.png new file mode 100644 index 000000000000..fe16cc659fd2 Binary files /dev/null and b/scaladoc/resources/dotty_res/images/gitter-icon-white.png differ diff --git a/scaladoc/resources/dotty_res/images/twitter-icon-black.png b/scaladoc/resources/dotty_res/images/twitter-icon-black.png new file mode 100644 index 000000000000..040ca1699567 Binary files /dev/null and b/scaladoc/resources/dotty_res/images/twitter-icon-black.png differ diff --git a/scaladoc/resources/dotty_res/images/twitter-icon-white.png b/scaladoc/resources/dotty_res/images/twitter-icon-white.png new file mode 100644 index 000000000000..66962e7d3c80 Binary files /dev/null and b/scaladoc/resources/dotty_res/images/twitter-icon-white.png differ diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 69e3814f55eb..4f13b266524f 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -661,7 +661,34 @@ footer .pull-right { content: url("../images/given.svg") } +#leftColumn .socials { + margin-left: 5%; + margin-right: 5%; +} + +footer .socials { + margin-left: 10px; + margin-right: 10px; + display: flex; + align-items: center; +} + +.social-icon { + padding-right: 5px; + padding-left: 5px; +} +.social-icon img { + height: 20px; + width: 20px; +} + +#generated-by { + position: absolute; + right: 10px; + display: flex; + align-items: center; +} /* Large Screens */ @media(min-width: 1100px) { diff --git a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala index cec8d648f0db..8f483f777848 100644 --- a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala +++ b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala @@ -38,6 +38,7 @@ object Scaladoc: sourceLinks: List[String] = Nil, revision: Option[String] = None, externalMappings: List[ExternalDocLink] = Nil, + socialLinks: List[SocialLinks] = Nil, identifiersToSkip: List[String] = Nil, regexesToSkip: List[String] = Nil, rootDocPath: Option[String] = None diff --git a/scaladoc/src/dotty/tools/scaladoc/ScaladocArgs.scala b/scaladoc/src/dotty/tools/scaladoc/ScaladocArgs.scala index ac45d706b805..19128206cd5e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/ScaladocArgs.scala +++ b/scaladoc/src/dotty/tools/scaladoc/ScaladocArgs.scala @@ -36,6 +36,11 @@ class ScaladocArgs extends SettingGroup with CommonScalaSettings: "Mapping between regexes matching classpath entries and external documentation. " + "'regex::[scaladoc|scaladoc|javadoc]::path' syntax is used") + val socialLinks: Setting[List[String]] = + MultiStringSetting("-social-links", "social-links", + "Links to social sites. '[github|twitter|gitter|discord]::link' syntax is used. " + + "'custom::link::white_icon_name::black_icon_name' is also allowed, in this case icons must be present in 'images/'' directory.") + val deprecatedSkipPackages: Setting[List[String]] = MultiStringSetting("-skip-packages", "packages", "Deprecated, please use `-skip-by-id` or `-skip-by-regex`") @@ -49,7 +54,7 @@ class ScaladocArgs extends SettingGroup with CommonScalaSettings: StringSetting("-doc-root-content", "path", "The file from which the root package documentation should be imported.", "") def scaladocSpecificSettings: Set[Setting[_]] = - Set(sourceLinks, syntax, revision, externalDocumentationMappings, skipById, skipByRegex, deprecatedSkipPackages, docRootContent) + Set(sourceLinks, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent) object ScaladocArgs: def extract(args: List[String], rootCtx: CompilerContext):(Scaladoc.Args, CompilerContext) = @@ -119,6 +124,14 @@ object ScaladocArgs: ) ) + val socialLinksParsed = + socialLinks.get.flatMap { s => + SocialLinks.parse(s).fold(left => { + report.warning(left) + None + },right => Some(right)) + } + unsupportedSettings.filter(s => s.get != s.default).foreach { s => report.warning(s"Setting ${s.name} is currently not supported.") } @@ -142,6 +155,7 @@ object ScaladocArgs: sourceLinks.get, revision.nonDefault, externalMappings, + socialLinksParsed, skipById.get ++ deprecatedSkipPackages.get, skipByRegex.get, docRootContent.nonDefault diff --git a/scaladoc/src/dotty/tools/scaladoc/SocialLinks.scala b/scaladoc/src/dotty/tools/scaladoc/SocialLinks.scala new file mode 100644 index 000000000000..4b2f43202e25 --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/SocialLinks.scala @@ -0,0 +1,30 @@ +package dotty.tools.scaladoc + +import java.nio.file.Path +import java.nio.file.Paths +import dotty.tools.dotc.core.Contexts.Context + +enum SocialLinks(val url: String, val whiteIconName: String, val blackIconName: String): + case Github(ghUrl: String) extends SocialLinks(ghUrl, "github-icon-white.png", "github-icon-black.png") + case Twitter(tUrl: String) extends SocialLinks(tUrl, "twitter-icon-white.png", "twitter-icon-black.png") + case Gitter(gUrl: String) extends SocialLinks(gUrl, "gitter-icon-white.png", "gitter-icon-black.png") + case Discord(dUrl: String) extends SocialLinks(dUrl, "discord-icon-white.png", "discord-icon-black.png") + case Custom(cUrl: String, cWhiteIconName: String, cBlackIconName: String) extends SocialLinks(cUrl, cWhiteIconName, cBlackIconName) + +object SocialLinks: + def parse(s: String): Either[String, SocialLinks] = + val errorPrefix = s"Social links arg $s is invalid: " + val splitted = s.split("::") + splitted.head match { + case "custom" if splitted.size == 4 => Right(Custom(splitted(1), splitted(2), splitted(3))) + case "custom" => Left(errorPrefix + "For 'custom' arg expected three arguments: url, white icon name and black icon name") + case "github" if splitted.size == 2 => Right(Github(splitted(1))) + case "github" => Left(errorPrefix + "For 'github' arg expected one argument: url") + case "twitter" if splitted.size == 2 => Right(Twitter(splitted(1))) + case "twitter" => Left(errorPrefix + "For 'twitter' arg expected one argument: url") + case "gitter" if splitted.size == 2 => Right(Gitter(splitted(1))) + case "gitter" => Left(errorPrefix + "For 'gitter' arg expected one argument: url") + case "discord" if splitted.size == 2 => Right(Discord(splitted(1))) + case "discord" => Left(errorPrefix + "For 'discord' arg expected one argument: url") + case _ => Left(errorPrefix) + } diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala index 307b6d6bb740..9b2c87bc0cb8 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala @@ -172,6 +172,16 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx ) renderNested(navigablePage)._2 + private def hasSocialLinks = !args.socialLinks.isEmpty + + private def socialLinks(whiteIcon: Boolean = true) = + val icon = (link: SocialLinks) => if whiteIcon then link.whiteIconName else link.blackIconName + args.socialLinks.map { link => + a(href := link.url)( + span(cls := s"social-icon", Attr("data-icon-path") := icon(link)) + ) + } + private def mkFrame(link: Link, parents: Vector[Link], content: => AppliedTag): AppliedTag = val projectLogo = args.projectLogo.map { path => @@ -195,6 +205,9 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx ), span( args.projectVersion.map(v => div(cls:="projectVersion")(v)).toList + ), + div(cls := "socials")( + socialLinks() ) ), div(id := "paneSearch"), @@ -220,14 +233,20 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx raw(" Back to top") ) ), - raw("Generated by "), - a(href := "https://github.com/lampepfl/dotty/tree/master/scaladoc")( - img( - src := resolveRoot(link.dri, "images/scaladoc_logo.svg"), - alt := "scaladoc", - cls := "scaladoc_logo" + div(cls := "socials")( + if hasSocialLinks then Seq(raw("Social links ")) else Nil, + socialLinks(whiteIcon = false) + ), + div(id := "generated-by")( + raw("Generated by "), + a(href := "https://github.com/lampepfl/dotty/tree/master/scaladoc")( + img( + src := resolveRoot(link.dri, "images/scaladoc_logo.svg"), + alt := "scaladoc", + cls := "scaladoc_logo" + ) ) - ) ) ) ) + ) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala index fc7e86102865..06c8108d6875 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala @@ -138,6 +138,14 @@ trait Resources(using ctx: DocContext) extends Locations, Writer: dottyRes("images/enum.svg"), dottyRes("images/enum_comp.svg"), dottyRes("images/given.svg"), + dottyRes("images/github-icon-black.png"), + dottyRes("images/github-icon-white.png"), + dottyRes("images/discord-icon-black.png"), + dottyRes("images/discord-icon-white.png"), + dottyRes("images/twitter-icon-black.png"), + dottyRes("images/twitter-icon-white.png"), + dottyRes("images/gitter-icon-black.png"), + dottyRes("images/gitter-icon-white.png"), searchData(pages) )