diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 101de48b79bf..a3a78ca71adc 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -1,5 +1,7 @@ index: index.md subsection: + - title: Blog + directory: blog - title: Usage directory: docs/usage subsection: diff --git a/scaladoc/src/dotty/tools/scaladoc/site/SidebarParser.scala b/scaladoc/src/dotty/tools/scaladoc/site/SidebarParser.scala index 9d793c403b2d..da402c6f0fed 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/SidebarParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/SidebarParser.scala @@ -30,14 +30,16 @@ object Sidebar: private object RawInputTypeRef extends TypeReference[RawInput] - private def toSidebar(r: RawInput)(using CompilerContext): Sidebar = r match + private def toSidebar(r: RawInput)(using CompilerContext): Option[Sidebar] = r match case RawInput(title, page, index, subsection, dir, hidden) if page.nonEmpty && index.isEmpty && subsection.isEmpty() => - Sidebar.Page(Option.when(title.nonEmpty)(title), page, hidden) + Some(Sidebar.Page(Option.when(title.nonEmpty)(title), page, hidden)) case RawInput(title, page, index, subsection, dir, hidden) if page.isEmpty && (!subsection.isEmpty() || !index.isEmpty()) => - Sidebar.Category(Option.when(title.nonEmpty)(title), Option.when(index.nonEmpty)(index), subsection.asScala.map(toSidebar).toList, Option.when(dir.nonEmpty)(dir)) + Some(Sidebar.Category(Option.when(title.nonEmpty)(title), Option.when(index.nonEmpty)(index), subsection.asScala.flatMap(toSidebar).toList, Option.when(dir.nonEmpty)(dir))) + case RawInput(title, page, index, subsection, dir, hidden) if page.isEmpty && title == "Blog" && dir.nonEmpty => + Some(Sidebar.Category(Option.when(title.nonEmpty)(title), None, List.empty, Option.when(dir.nonEmpty)(dir))) case RawInput(title, page, index, subsection, dir, hidden) => report.error(s"Error parsing YAML configuration file.\n$schemaMessage") - Sidebar.Page(None, page, hidden) + None private def schemaMessage: String = s"""Static site YAML configuration file should comply with the following description: @@ -51,6 +53,7 @@ object Sidebar: | subsection: # optional - If not provided, pages are loaded from the index directory | - | | # either index or subsection needs to be present + | # the only exception is subsection representing Blog which needs title == "Blog" and directory |: | title: # optional - Default value is file name. Title can be also set using front-matter. | page: @@ -76,7 +79,7 @@ object Sidebar: identity ) toSidebar(root) match - case c: Sidebar.Category => c + case Some(c: Sidebar.Category) => c case _ => report.error(s"Root element is not a subsection.\n$schemaMessage") Sidebar.Category(None, None, List.empty, None) diff --git a/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteLoader.scala b/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteLoader.scala index 0df7fa11c324..8c783ab31e2a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteLoader.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteLoader.scala @@ -89,7 +89,23 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite val templateFile = loadTemplateFile(file, title) LoadedTemplate(templateFile, List.empty, pathFromRoot.resolve(file.getName).toFile, hidden) } - val rootTemplate = LoadedTemplate(rootIndex, yamlRoot.nested.map(c => loadChild(ctx.docsPath)(c)) ++ loadBlog(), rootDest) + val blogDirectory = yamlRoot.nested.collect { + case blog @ Sidebar.Category(optionTitle, optionIndexPath, nested, dir) + if optionTitle.exists(_ == "Blog") => blog + }.headOption.flatMap(_.directory) + + val rootChildrenWithoutBlog = yamlRoot.nested.filter { + case Sidebar.Category(optionTitle, optionIndexPath, nested, dir) + if optionTitle.exists(_ == "Blog") => false + case _ => true + } + + val rootTemplate = + LoadedTemplate( + rootIndex, + rootChildrenWithoutBlog.map(c => loadChild(ctx.docsPath)(c)) ++ loadBlog(blogDirectory), + rootDest + ) val mappings = createMapping(rootTemplate) StaticSiteRoot(rootTemplate, mappings) } @@ -113,8 +129,9 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite StaticSiteRoot(withBlog, mappings) } - def loadBlog(): Option[LoadedTemplate] = { + def loadBlog(directory: Option[String] = None): Option[LoadedTemplate] = { type Date = (String, String, String) + val destDirectory = directory.getOrElse("_blog") val rootPath = ctx.blogPath if (!Files.exists(rootPath)) None else { @@ -131,7 +148,7 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite val indexTemplateOpt = indexPageOpt.map(p => loadTemplateFile(p.toFile)) val indexPage = indexTemplateOpt.getOrElse(emptyTemplate(rootPath.resolve("index.html").toFile, "Blog")) - val indexDest = ctx.docsPath.resolve("_blog").resolve("index.html") + val indexDest = ctx.docsPath.resolve(destDirectory).resolve("index.html") val regex = raw"(\d*)-(\d*)-(\d*)-(.*)".r def splitDateName(tf: TemplateFile): (Date, String) = tf.file.getName match case regex(year, month, day, name) => ((year, month, day), name) @@ -150,7 +167,7 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite .map { postFile => val templateFile = loadTemplateFile(postFile) val ((year, month, day), name) = splitDateName(templateFile) - val destPath = ctx.docsPath.resolve("_blog").resolve(year).resolve(month).resolve(day).resolve(name) + val destPath = ctx.docsPath.resolve(destDirectory).resolve(year).resolve(month).resolve(day).resolve(name) val date = dateFrom(templateFile, s"$year-$month-$day") date -> LoadedTemplate(templateFile, List.empty, destPath.toFile) }.sortBy(_._1).reverse.map(_._2)