Skip to content

Commit a6d4548

Browse files
committed
Consume sidebar.yaml in scala3doc
Now documentation generated by scala3doc has same layout as documentation build on http://dotty.epfl.ch/ Fix code highlighting in static pages
1 parent 2436ea7 commit a6d4548

File tree

9 files changed

+121
-51
lines changed

9 files changed

+121
-51
lines changed

project/Build.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,7 @@ object Build {
14811481
"com.vladsch.flexmark" % "flexmark-all" % "0.42.12",
14821482
"nl.big-o" % "liqp" % "0.6.7",
14831483
"args4j" % "args4j" % "2.33",
1484+
Dependencies.`jackson-dataformat-yaml`,
14841485

14851486
"org.jetbrains.dokka" % "dokka-test-api" % dokkaVersion % "test",
14861487
"com.novocode" % "junit-interface" % "0.11" % "test",

scala3doc/scala3-docs/_layouts/base.html

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
- css/color-brewer.css
66
extraJS:
77
- js/jquery.min.js
8-
- js/highlight.pack.js
98
- js/bootstrap.min.js
109
---
1110
<link rel="dns-prefetch" href="//fonts.googleapis.com">
@@ -16,16 +15,3 @@
1615

1716

1817
{{ content }}
19-
20-
<script>
21-
$(document).ready(function() {
22-
// Code hilighting (requires hilight.js to be loaded)
23-
$('pre code').each(function(i, block) {
24-
hljs.highlightBlock(block);
25-
});
26-
// Autoscroll to anchor
27-
if (window.location.hash.length > 0) {
28-
window.scrollTo(0, $(window.location.hash).offset().top - 90);
29-
}
30-
})
31-
</script>

scala3doc/scala3-docs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
</a>
2121
</li>
2222
<li class="nav-item">
23-
<a class="nav-link" href="{{ site.baseurl }}/blog/index.html">
23+
<a class="nav-link" href="docs/blog/index.html">
2424
Blog
2525
</a>
2626
</li>

scala3doc/scala3-docs/sidebar.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../docs/sidebar.yml
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package dotty.dokka
2+
package site
3+
4+
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.core.`type`.TypeReference;
7+
import collection.JavaConverters._
8+
import java.util.Optional
9+
10+
enum Sidebar:
11+
val title: String
12+
case Category(title: String, nested: List[Sidebar])
13+
case Page(title: String, url: String)
14+
15+
object Sidebar:
16+
case class RawInput(var title: String,var url: String, var subsection: JList[RawInput]):
17+
def this() = this("", "", JList())
18+
19+
def setTitle(t: String) = this.title = t
20+
def setUrl(u: String) = this.url = u
21+
def setSubsection(l: JList[RawInput]) = this.subsection = l
22+
23+
private object RawTypeRef extends TypeReference[JMap[String, JList[RawInput]]]
24+
25+
private def toSidebar(r: RawInput): Sidebar = r match
26+
case RawInput(title, url, list) if title.nonEmpty && url.nonEmpty && list.isEmpty() =>
27+
Sidebar.Page(title, url)
28+
case RawInput(title, url, list) if title.nonEmpty && url.isEmpty && !list.isEmpty() =>
29+
Sidebar.Category(title, list.asScala.map(toSidebar).toList)
30+
31+
def load(content: String): Seq[Sidebar] =
32+
val mapper = ObjectMapper(YAMLFactory())
33+
val raw = mapper.readValue(content, RawTypeRef)
34+
35+
raw.get("sidebar").asScala.toList.map(toSidebar)

scala3doc/src/dotty/dokka/site/StaticSiteContext.scala

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package dotty.dokka
22
package site
33

44
import java.io.File
5+
import java.nio.file.Files
6+
57

68
import org.jetbrains.dokka.base.parsers.MarkdownParser
79
import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
@@ -21,13 +23,22 @@ class StaticSiteContext(val root: File, sourceSets: Set[SourceSetWrapper]):
2123
def indexPage():Option[StaticPageNode] =
2224
val files = List(new File(root, "index.html"), new File(root, "index.md")).filter { _.exists() }
2325
if (files.size > 1) println(s"ERROR: Multiple root index pages found: ${files.map(_.getAbsolutePath)}") // TODO (#14): provide proper error handling
24-
loadFiles(files).headOption
26+
files.flatMap(loadTemplate(_, isBlog = false)).headOption.map(templateToPage)
2527

2628
lazy val layouts: Map[String, TemplateFile] =
2729
val layoutRoot = new File(root, "_layouts")
2830
val dirs: Array[File] = Option(layoutRoot.listFiles()).getOrElse(Array())
2931
dirs.map { it => loadTemplateFile(it) }.map { it => it.name() -> it }.toMap
3032

33+
lazy val sideBarConfig =
34+
val sidebarFile = root.toPath.resolve("sidebar.yml")
35+
if (!Files.exists(sidebarFile)) None
36+
else Some(Sidebar.load(Files.readAllLines(sidebarFile).asScala.mkString("\n")))
37+
38+
lazy val templates: Seq[LoadedTemplate] = sideBarConfig.fold(loadAllFiles())(_.map(loadSidebarContent))
39+
40+
lazy val pages = templates.map(templateToPage)
41+
3142
private def isValidTemplate(file: File): Boolean =
3243
(file.isDirectory && !file.getName.startsWith("_")) ||
3344
file.getName.endsWith(".md") ||
@@ -38,7 +49,7 @@ class StaticSiteContext(val root: File, sourceSets: Set[SourceSetWrapper]):
3849
if (!isValidTemplate(from)) None else
3950
try
4051
val topLevelFiles = if isBlog then Seq(from, new File(from, "_posts")) else Seq(from)
41-
val allFiles = topLevelFiles.filter(_.isDirectory).flatMap(_.listFiles())
52+
val allFiles = topLevelFiles.filter(_.isDirectory).flatMap(_.listFiles())
4253
val (indexes, children) = allFiles.flatMap(loadTemplate(_)).partition(_.templateFile.isIndexPage())
4354
if (indexes.size > 1)
4455
println(s"ERROR: Multiple index pages for $from found in ${indexes.map(_.file)}") // TODO (#14): provide proper error handling
@@ -68,36 +79,38 @@ class StaticSiteContext(val root: File, sourceSets: Set[SourceSetWrapper]):
6879
new PropertyContainer(JMap())
6980
)
7081

71-
def loadAllFiles() =
82+
private def loadSidebarContent(entry: Sidebar): LoadedTemplate = entry match
83+
case Sidebar.Page(title, url) =>
84+
val isBlog = title == "Blog"
85+
val path = if isBlog then "blog" else url.stripSuffix(".html") + ".md"
86+
val file = root.toPath.resolve(path) // Add support for.html files!
87+
val LoadedTemplate(template, children, tFile) = loadTemplate(file.toFile, isBlog).get // Add proper logging if file does not exisits
88+
LoadedTemplate(template.copy(settings = template.settings + ("title" -> List(title))), children, tFile)
89+
case Sidebar.Category(title, nested) =>
90+
val fakeFile = new File(root, title)
91+
LoadedTemplate(emptyTemplate(fakeFile), nested.map(loadSidebarContent), fakeFile)
92+
93+
private def loadAllFiles() =
7294
def dir(name: String)= List(new File(root, name)).filter(_.isDirectory)
73-
loadFiles(dir("docs").flatMap(_.listFiles())) ++ loadFiles(dir("blog"), isBlog = true)
74-
75-
def loadFiles(files: List[File], isBlog: Boolean = false): List[StaticPageNode] =
76-
val all = files.flatMap(loadTemplate(_, isBlog))
77-
def flatten(it: LoadedTemplate): List[String] =
78-
List(it.relativePath(root)) ++ it.children.flatMap(flatten)
95+
dir("docs").flatMap(_.listFiles()).flatMap(loadTemplate(_, isBlog = false))
96+
++ dir("blog").flatMap(loadTemplate(_, isBlog = true))
7997

98+
def templateToPage(myTemplate: LoadedTemplate): StaticPageNode =
8099
def pathToDRI(path: String) = mkDRI(s"_.$path")
81-
82-
val driMap = all.flatMap(flatten).map(it => it -> pathToDRI(it)).toMap
83-
84-
def templateToPage(myTemplate: LoadedTemplate): StaticPageNode =
85-
val dri = pathToDRI(myTemplate.relativePath(root))
86-
val content = new PartiallyRenderedContent(
87-
myTemplate.templateFile,
88-
this,
89-
JList(),
90-
new DCI(Set(dri).asJava, ContentKind.Empty),
91-
sourceSets.toDisplay,
92-
JSet()
93-
)
94-
StaticPageNode(
95-
myTemplate.templateFile,
96-
myTemplate.templateFile.title(),
97-
content,
98-
JSet(dri),
99-
JList(),
100-
(myTemplate.children.map(templateToPage)).asJava
101-
)
102-
103-
all.map(templateToPage)
100+
val dri = pathToDRI(myTemplate.relativePath(root))
101+
val content = new PartiallyRenderedContent(
102+
myTemplate.templateFile,
103+
this,
104+
JList(),
105+
new DCI(Set(dri).asJava, ContentKind.Empty),
106+
sourceSets.toDisplay,
107+
JSet()
108+
)
109+
StaticPageNode(
110+
myTemplate.templateFile,
111+
myTemplate.templateFile.title(),
112+
content,
113+
JSet(dri),
114+
JList(),
115+
(myTemplate.children.map(templateToPage)).asJava
116+
)

scala3doc/src/dotty/dokka/site/processors.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class SitePagesCreator(ctx: Option[StaticSiteContext]) extends BaseStaticSitePro
9090
override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode =
9191
val (contentPage, others) = input.getChildren.asScala.toList.partition { _.isInstanceOf[ContentPage] }
9292
val modifiedModuleRoot = processRootPage(input, contentPage)
93-
val (indexes, children) = ctx.loadAllFiles().partition(_.template.isIndexPage())
93+
val (indexes, children) = ctx.pages.partition(_.template.isIndexPage())
9494
// TODO (#14): provide proper error handling
9595
if (indexes.size > 1) println("ERROR: Multiple index pages found $indexes}")
9696

@@ -117,13 +117,21 @@ class RootIndexPageCreator(ctx: Option[StaticSiteContext]) extends BaseStaticSit
117117
val (navigations, rest) = nonContent.partition { _.isInstanceOf[NavigationPage] }
118118
val modifiedNavigation = navigations.map { it =>
119119
val root = it.asInstanceOf[NavigationPage].getRoot
120-
val (api, rest) = root.getChildren.asScala.partition { _.getDri == apiPageDRI }
120+
val api = root.getChildren.asScala.filter(_.getDri == apiPageDRI)
121+
122+
def toNavigationNode(page: StaticPageNode): NavigationNode = NavigationNode(
123+
page.title(),
124+
page.getDri.asScala.head,
125+
root.getSourceSets,
126+
page.getChildren.asScala.collect { case p: StaticPageNode => toNavigationNode(p)}.asJava
127+
)
128+
121129
new NavigationPage(
122130
new NavigationNode(
123131
input.getName,
124132
docsRootDRI,
125133
root.getSourceSets,
126-
(rest ++ api).asJava
134+
(ctx.pages.map(toNavigationNode) ++ api).asJava
127135
)
128136
)
129137
}

scala3doc/src/dotty/dokka/site/templates.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ case class TemplateFile(
4747
val file: File,
4848
val isHtml: Boolean,
4949
val rawCode: String,
50-
private val settings: Map[String, List[String]]
50+
val settings: Map[String, List[String]]
5151
):
5252

5353
private def stringSetting(name: String): Option[String] =
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dotty.dokka.site
2+
3+
import org.junit.Test
4+
import org.junit.Assert._
5+
6+
// TODO add negaitve and more details tests
7+
class SidebarParserTest:
8+
9+
private val sidebar = """sidebar:
10+
- title: Blog
11+
url: blog/index.html
12+
- title: Reference
13+
subsection:
14+
- title: Overview
15+
url: docs/reference/overview.html
16+
- title: New Types
17+
subsection:
18+
- title: Intersection types
19+
url: docs/reference/new-types/intersection-types.html
20+
- title: Union types
21+
url: docs/reference/new-types/union-types.html
22+
"""
23+
24+
@Test
25+
def loadSidebar(): Unit =
26+
assertEquals(2, Sidebar.load(sidebar).size)

0 commit comments

Comments
 (0)