Skip to content

Commit 6cc1ee1

Browse files
authored
Merge pull request #12993 from BarkingBad/scaladoc/site-fixes
Various static site fixes
2 parents ff044e0 + bd6d763 commit 6cc1ee1

File tree

10 files changed

+85
-44
lines changed

10 files changed

+85
-44
lines changed

scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
4545
val msg = s"ERROR: Multiple index pages for doc found ${indexes.map(_.file)}"
4646
report.error(msg)
4747

48-
val templatePages =
49-
(templates ++ siteContext.indexTemplate()).map(templateToPage(_, siteContext))
48+
val templatePages = templates.map(templateToPage(_, siteContext))
49+
5050
indexes.headOption match
5151
case None if templatePages.isEmpty=>
5252
rootPckPage.withTitle(args.name)
@@ -63,10 +63,29 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
6363
link = navigablePage.link.copy(dri = docsRootDRI),
6464
children = Nil
6565
))
66-
case Some(site) =>
67-
site.orphanedTemplates.map(templateToPage(_, site))
66+
case Some(siteContext) =>
67+
(siteContext.orphanedTemplates :+ siteContext.indexTemplate()).map(templateToPage(_, siteContext))
68+
69+
/**
70+
* Here we have to retrive index pages from hidden pages and replace fake index pages in navigable page tree.
71+
*/
72+
private def getAllPages: Seq[Page] =
73+
74+
def traversePages(page: Page): (Page, Seq[Page]) =
75+
val (newChildren, newPagesToRemove): (Seq[Page], Seq[Page]) = page.children.map(traversePages(_)).foldLeft((Seq[Page](), Seq[Page]())) {
76+
case ((pAcc, ptrAcc), (p, ptr)) => (pAcc :+ p, ptrAcc ++ ptr)
77+
}
78+
hiddenPages.find(_.link == page.link) match
79+
case None =>
80+
(page.copy(children = newChildren), newPagesToRemove)
81+
case Some(newPage) =>
82+
(newPage.copy(children = newChildren), newPagesToRemove :+ newPage)
83+
84+
val (newNavigablePage, pagesToRemove) = traversePages(navigablePage)
6885

69-
val allPages = navigablePage +: hiddenPages
86+
newNavigablePage +: hiddenPages.filterNot(pagesToRemove.contains)
87+
88+
val allPages = getAllPages
7089

7190
def renderContent(page: Page) = page.content match
7291
case m: Member =>
@@ -160,13 +179,16 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
160179

161180
def renderNested(nav: Page, toplevel: Boolean = false): (Boolean, AppliedTag) =
162181
val isSelected = nav.link.dri == pageLink.dri
163-
def linkHtml(exapnded: Boolean = false) =
164-
val attrs = if (isSelected || toplevel) Seq(cls := "selected expanded") else Nil
182+
def linkHtml(expanded: Boolean = false) =
183+
val attrs: Seq[String] = Seq(
184+
Option.when(isSelected)("selected"),
185+
Option.when(expanded)("expanded")
186+
).flatten
165187
val icon = nav.content match {
166188
case m: Member => navigationIcon(m)
167189
case _ => Nil
168190
}
169-
Seq(a(href := pathToPage(pageLink.dri, nav.link.dri), attrs)(icon, span(nav.link.name)))
191+
Seq(a(href := pathToPage(pageLink.dri, nav.link.dri), cls := attrs.mkString(" "))(icon, span(nav.link.name)))
170192

171193
nav.children match
172194
case Nil => isSelected -> div(linkHtml())
@@ -177,9 +199,10 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
177199
if expanded || isSelected || toplevel then Seq(cls := "expanded") else Nil
178200
(isSelected || expanded) -> div(attr)(
179201
linkHtml(expanded),
180-
span(cls := "ar"),
202+
if toplevel then Nil else span(cls := "ar"),
181203
nested.map(_._2)
182204
)
205+
183206
renderNested(navigablePage, toplevel = true)._2
184207

185208
private def canonicalUrl(l: String): AppliedTag | String =

scaladoc/src/dotty/tools/scaladoc/renderers/SiteRenderer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ trait SiteRenderer(using DocContext) extends Locations:
2222
def templateToPage(t: LoadedTemplate, staticSiteCtx: StaticSiteContext): Page =
2323
val dri = staticSiteCtx.driFor(t.file.toPath)
2424
val content = ResolvedTemplate(t, staticSiteCtx)
25-
Page(Link(t.templateFile.title, dri), content, t.children.map(templateToPage(_, staticSiteCtx)))
25+
Page(Link(t.templateFile.title.name, dri), content, t.children.map(templateToPage(_, staticSiteCtx)))
2626

2727
private val HashRegex = "([^#]+)(#.+)".r
2828

scaladoc/src/dotty/tools/scaladoc/site/LoadedTemplate.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ case class LoadedTemplate(
3333
val site = templateFile.settings.getOrElse("page", Map.empty).asInstanceOf[Map[String, Object]]
3434
site.asJava.entrySet() ++ JSet(
3535
LazyEntry("url", () => ctx.relativePath(LoadedTemplate.this).toString),
36-
LazyEntry("title", () => templateFile.title),
36+
LazyEntry("title", () => templateFile.title.name),
3737
LazyEntry("excerpt", () => brief(ctx))
3838
)
3939

@@ -49,6 +49,6 @@ case class LoadedTemplate(
4949

5050
val updatedSettings = templateFile.settings ++ ctx.projectWideProperties +
5151
("site" -> (getMap("site") + ("posts" -> posts))) + ("urls" -> sourceLinks.toMap) +
52-
("page" -> (getMap("page") + ("title" -> templateFile.title)))
52+
("page" -> (getMap("page") + ("title" -> templateFile.title.name)))
5353

5454
templateFile.resolveInner(RenderingContext(updatedSettings, ctx.layouts))(using ctx)

scaladoc/src/dotty/tools/scaladoc/site/SidebarParser.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import collection.JavaConverters._
88
import java.util.Optional
99

1010
enum Sidebar:
11-
val title: String
12-
case Category(title: String, nested: List[Sidebar])
13-
case Page(title: String, url: String)
11+
case Category(title: String, url: Option[String], nested: List[Sidebar])
12+
case Page(title: Option[String], url: String)
1413

1514
object Sidebar:
16-
case class RawInput(var title: String,var url: String, var subsection: JList[RawInput]):
15+
case class RawInput(var title: String, var url: String, var subsection: JList[RawInput]):
1716
def this() = this("", "", JList())
1817

1918
def setTitle(t: String) = this.title = t
@@ -24,10 +23,10 @@ object Sidebar:
2423
private object RawTypeRef extends TypeReference[RawInnerTpe]
2524

2625
private def toSidebar(r: RawInput): Sidebar = r match
27-
case RawInput(title, url, list) if title.nonEmpty && url.nonEmpty && list.isEmpty() || title == "Blog" =>
28-
Sidebar.Page(title, url)
29-
case RawInput(title, url, list) if title.nonEmpty && url.isEmpty && !list.isEmpty() =>
30-
Sidebar.Category(title, list.asScala.map(toSidebar).toList)
26+
case RawInput(title, url, list) if url.nonEmpty && list.isEmpty() || title == "Blog" =>
27+
Sidebar.Page(Option.when(title.nonEmpty)(title), url)
28+
case RawInput(title, url, list) if title.nonEmpty && !list.isEmpty() =>
29+
Sidebar.Category(title, Option.when(url.nonEmpty)(url), list.asScala.map(toSidebar).toList)
3130

3231
def load(content: String): Seq[Sidebar] =
3332
val mapper = ObjectMapper(YAMLFactory())

scaladoc/src/dotty/tools/scaladoc/site/StaticSiteContext.scala

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ class StaticSiteContext(
1919

2020
var memberLinkResolver: String => Option[DRI] = _ => None
2121

22-
def indexTemplate(): Seq[LoadedTemplate] =
22+
def indexTemplate(): LoadedTemplate =
2323
val files = List(new File(root, "index.html"), new File(root, "index.md")).filter { _.exists() }
2424

2525
if files.size > 1 then
2626
val msg = s"ERROR: Multiple root index pages found: ${files.map(_.getAbsolutePath)}"
2727
report.error(msg)
2828

29-
files.flatMap(loadTemplate(_, isBlog = false)).take(1)
29+
files.flatMap(loadTemplate(_, isBlog = false)).headOption.getOrElse {
30+
val fakeFile = new File(root, "index.html")
31+
LoadedTemplate(emptyTemplate(fakeFile, "index"), List.empty, fakeFile)
32+
}
3033

3134
lazy val layouts: Map[String, TemplateFile] =
3235
val layoutRoot = new File(root, "_layouts")
@@ -39,7 +42,7 @@ class StaticSiteContext(
3942
else Some(Sidebar.load(Files.readAllLines(sidebarFile).asScala.mkString("\n")))
4043

4144
lazy val templates: Seq[LoadedTemplate] =
42-
sideBarConfig.fold(loadAllFiles().sortBy(_.templateFile.title))(_.map(loadSidebarContent))
45+
sideBarConfig.fold(loadAllFiles().sortBy(_.templateFile.title.name))(_.map(loadSidebarContent))
4346

4447
lazy val orphanedTemplates: Seq[LoadedTemplate] = {
4548
def doFlatten(t: LoadedTemplate): Seq[Path] =
@@ -93,7 +96,7 @@ class StaticSiteContext(
9396
val pageSettings = p.templateFile.settings.get("page").collect{ case m: Map[String @unchecked, _] => m }
9497
pageSettings.flatMap(_.get("date").collect{ case s: String => s}).getOrElse(default) // blogs without date are last
9598

96-
val processedChildren: Seq[LoadedTemplate] = if !isBlog then children.sortBy(_.templateFile.title) else
99+
val processedChildren: Seq[LoadedTemplate] = if !isBlog then children.sortBy(_.templateFile.title.name) else
97100
children.sortBy(dateFrom(_)).reverse
98101

99102
processedChildren.foreach { child =>
@@ -108,10 +111,10 @@ class StaticSiteContext(
108111

109112
val processedTemplate = // Set provided name as arg in page for `docs`
110113
if from.getParentFile.toPath == docsPath && templateFile.isIndexPage() then
111-
if templateFile.title != "index" then
114+
if templateFile.title.name != "index" then
112115
report.warn("Property `title` will be overridden by project name", from)
113116

114-
templateFile.copy(title = args.name)
117+
templateFile.copy(title = TemplateName.FilenameDefined(args.name))
115118
else templateFile
116119

117120
Some(LoadedTemplate(processedTemplate, processedChildren.toList, from))
@@ -122,20 +125,31 @@ class StaticSiteContext(
122125
None
123126

124127
private def loadSidebarContent(entry: Sidebar): LoadedTemplate = entry match
125-
case Sidebar.Page(title, url) =>
126-
val isBlog = title == "Blog"
128+
case Sidebar.Page(optionTitle, url) =>
129+
val isBlog = optionTitle == Some("Blog")
127130
val path = if isBlog then "blog" else
128131
if Files.exists(root.toPath.resolve(url)) then url
129132
else url.stripSuffix(".html") + ".md"
130133

131134
val file = root.toPath.resolve(path).toFile
132135
val LoadedTemplate(template, children, _) = loadTemplate(file, isBlog).get // Add proper logging if file does not exisits
133-
LoadedTemplate(template.copy(settings = template.settings + ("title" -> title), file = file), children, file)
134-
135-
case Sidebar.Category(title, nested) =>
136-
// Add support for index.html/index.md files!
137-
val fakeFile = new File(new File(root, "docs"), title)
138-
LoadedTemplate(emptyTemplate(fakeFile, title), nested.map(loadSidebarContent), fakeFile)
136+
optionTitle match
137+
case Some(title) =>
138+
val newTitle = template.title match
139+
case t: TemplateName.YamlDefined => t
140+
case _: TemplateName.FilenameDefined => TemplateName.SidebarDefined(title)
141+
case t: TemplateName.SidebarDefined => t // should never reach this path
142+
LoadedTemplate(template.copy(settings = template.settings + ("title" -> newTitle.name), file = file, title = newTitle), children, file)
143+
case None =>
144+
LoadedTemplate(template.copy(settings = template.settings, file = file), children, file)
145+
146+
case Sidebar.Category(title, optionUrl, nested) =>
147+
optionUrl match
148+
case Some(url) => // There is an index page for section, let's load it
149+
loadSidebarContent(Sidebar.Page(Some(title), url)).copy(children = nested.map(loadSidebarContent))
150+
case None => // No index page, let's create default fake file.
151+
val fakeFile = new File(new File(root, "docs"), title)
152+
LoadedTemplate(emptyTemplate(fakeFile, title), nested.map(loadSidebarContent), fakeFile)
139153

140154
private def loadAllFiles() =
141155
def dir(name: String)= List(new File(root, name)).filter(_.isDirectory)

scaladoc/src/dotty/tools/scaladoc/site/common.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension
1717

1818
import scala.collection.JavaConverters._
1919

20-
val docsRootDRI: DRI = DRI(location = "docs", symbolUUID = staticFileSymbolUUID)
21-
val apiPageDRI: DRI = DRI(location = "api")
20+
val docsRootDRI: DRI = DRI(location = "docs/index", symbolUUID = staticFileSymbolUUID)
21+
val apiPageDRI: DRI = DRI(location = "api/index")
2222

2323
val defaultMarkdownOptions: DataHolder =
2424
new MutableDataSet()
@@ -45,7 +45,7 @@ def emptyTemplate(file: File, title: String): TemplateFile = TemplateFile(
4545
rawCode = "",
4646
settings = Map.empty,
4747
name = file.getName.stripSuffix(".html"),
48-
title = title,
48+
title = TemplateName.FilenameDefined(title),
4949
hasFrame = true,
5050
resources = List.empty,
5151
layout = None,
@@ -104,7 +104,7 @@ def loadTemplateFile(file: File): TemplateFile = {
104104
rawCode = content.mkString(LineSeparator),
105105
settings = settings,
106106
name = name,
107-
title = stringSetting(allSettings, "title").getOrElse(name),
107+
title = stringSetting(allSettings, "title").map(TemplateName.YamlDefined(_)).getOrElse(TemplateName.FilenameDefined(name)),
108108
hasFrame = !stringSetting(allSettings, "hasFrame").contains("false"),
109109
resources = (listSetting(allSettings, "extraCSS") ++ listSetting(allSettings, "extraJS")).flatten.toList,
110110
layout = stringSetting(allSettings, "layout"),

scaladoc/src/dotty/tools/scaladoc/site/templates.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ case class RenderingContext(
3535
)
3636

3737
case class ResolvedPage(code: String, resources: List[String] = Nil)
38+
39+
enum TemplateName(val name: String):
40+
case YamlDefined(override val name: String) extends TemplateName(name)
41+
case SidebarDefined(override val name: String) extends TemplateName(name)
42+
case FilenameDefined(override val name: String) extends TemplateName(name)
43+
3844
/**
3945
* case class for the template files.
4046
* Template file is a file `.md` or `.html` handling settings.
@@ -49,7 +55,7 @@ case class TemplateFile(
4955
rawCode: String,
5056
settings: Map[String, Object],
5157
name: String,
52-
title: String,
58+
title: TemplateName,
5359
hasFrame: Boolean,
5460
resources: List[String],
5561
layout: Option[String],

scaladoc/test/dotty/tools/scaladoc/site/NavigationTest.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ class NavigationTest extends BaseHtmlTest:
2929
NavMenuTestEntry("Nested in a directory", "dir/nested.html", Nil)
3030
)),
3131
NavMenuTestEntry("Adoc", "Adoc.html", Seq()),
32-
NavMenuTestEntry("Basic test", "../index.html", Seq()),
3332
NavMenuTestEntry("API", "../api/index.html", Seq(
3433
NavMenuTestEntry("tests.site", "../api/tests/site.html", Seq(
3534
NavMenuTestEntry("BrokenLink", "../api/tests/site/BrokenLink.html", Nil),
@@ -47,4 +46,4 @@ class NavigationTest extends BaseHtmlTest:
4746
))
4847

4948
testNavMenu("docs/Adoc.html", topLevelNav)
50-
}
49+
}

scaladoc/test/dotty/tools/scaladoc/site/SiteGeneratationTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class SiteGeneratationTest extends BaseHtmlTest:
4141
checkFile("docs/index.html")(title = projectName, header = s"$projectName in header")
4242

4343
def testMainIndexPage()(using ProjectContext) =
44-
checkFile("index.html")(title = "Basic test", header = "Header", parents = Seq(projectName), indexLinks)
44+
checkFile("index.html")(title = "Basic test", header = "Header", parents = Seq(), indexLinks)
4545

4646
def testApiPages(
4747
mainTitle: String = "API",
@@ -110,4 +110,4 @@ class SiteGeneratationTest extends BaseHtmlTest:
110110
"dir/nested.svg"
111111
)
112112
}
113-
}
113+
}

scaladoc/test/dotty/tools/scaladoc/site/TemplateFileTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class TemplateFileTests:
4343
|code""".stripMargin
4444
) { t =>
4545
assertEquals(t.rawCode, "code")
46-
assertEquals(t.title, "myTitle")
46+
assertEquals(t.title.name, "myTitle")
4747
}
4848

4949

0 commit comments

Comments
 (0)