Skip to content

Make navigation much snappier #10776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 0 additions & 55 deletions scala3doc/resources/dotty_res/scripts/fast-navigation-loader.js

This file was deleted.

4 changes: 4 additions & 0 deletions scala3doc/resources/dotty_res/scripts/ux.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ window.addEventListener("DOMContentLoaded", () => {
}
}

$("#sideMenu2 span").on('click', function(){
$(this).parent().toggleClass("expanded")
});


if (location.hash) {
var selected = document.getElementById(location.hash.substring(1));
Expand Down
122 changes: 71 additions & 51 deletions scala3doc/resources/dotty_res/styles/scalastyle.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@ th {
}

/* Left bar */
#sideMenu {
overflow-y: auto;
scrollbar-width: thin;
height: 100%;
font-size: var(--leftbar-font-size);
}
#paneSearch {
display: none;
}
Expand Down Expand Up @@ -159,63 +153,88 @@ th {
width: 116px;
}

.sideMenuPart {
padding-left: 1em;
/* Navigation */
#sideMenu2 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any clash with sideMenu name, that we use sideMenu2?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you remove old sideMenu styles and elements

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

overflow-y: auto;
scrollbar-width: thin;
height: 100%;
font-size: var(--leftbar-font-size);
}

/* divs in sidebar represent entry and its children */
#sideMenu2 div {
padding-left: 0.7em;
position: relative;
display: none;
}

#sideMenu2 div.expanded {
display: block;
}

/* hide children of hidden entries even if are expanded */
#sideMenu2 div>div.expanded {
display: none;
}

/* show direct children of currently exmanded node*/
#sideMenu2 div.expanded>div {
display: block;
}

/* always show top level entry*/
#sideMenu2>div{
display: block;
}
.sideMenuPart a {

/* 'a's in side menu represent text of entry with link */
#sideMenu2 a {
align-items: center;
flex: 1;
overflow-x: hidden;
overflow-wrap: anywhere;
color: var(--leftbar-fg);
margin-right: .5rem;
padding: 7px 0;
}
.sideMenuPart > .overview {
display: flex;
align-items: center;
position: relative;
user-select: none;
}
.sideMenuPart > .overview::before {
width: var(--side-width);
box-sizing: border-box;
content: '';
top: 0;
right: 0;
bottom: 0;
position: absolute;
z-index: 1;
}
.sideMenuPart > .overview:hover::before {
background: var(--leftbar-hover-bg);
padding-top: 3px;
padding-bottom: 3px;
margin-top: 1px;
margin-bottom: 1px;
width: 100%;
display: block;
/* This trick adds selected bachground stratching to the lef side of screen */
margin-left: calc(0px - var(--side-width));
padding-left: var(--side-width);
width: calc(2 * var(--side-width));
}
.sideMenuPart > .overview:hover > a {
color: var(--leftbar-hover-fg);

#sideMenu2 a::before {
margin-left: -12em;
width: 12em;
background: red;
}
.sideMenuPart[data-active] > .overview::before {

#sideMenu2 a.selected {
background: var(--leftbar-current-bg);
}
.sideMenuPart[data-active] > .overview > a {
font-weight: bold;
color: var(--leftbar-current-fg);
}
.sideMenuPart.hidden > .sideMenuPart {
height: 0;
visibility: hidden;
}
.overview a, .overview .navButton {
z-index: 3;

#sideMenu2 a:hover {
color: var(--leftbar-hover-fg);
background: var(--leftbar-hover-bg);
}
.sideMenuPart .navButton {

/* spans represent a expand button */
#sideMenu2 span {
align-items: center;
display: flex;
justify-content: flex-end;
padding: 7px 10px;
cursor: pointer;
position: absolute;
right: 1em;
top: 0px;
padding: 4px;
}
.sideMenuPart .navButtonContent::before {
content: "\e905"; /* arrow up */

#sideMenu2 span::before {
content: "\e903"; /* arrow down */
font-family: "dotty-icons" !important;
font-size: 20px;
line-height: var(--leftbar-font-size);
Expand All @@ -225,10 +244,11 @@ th {
align-items: center;
justify-content: center;
}
.sideMenuPart.hidden .navButtonContent::before {
content: "\e903"; /* arrow down */
#sideMenu2 .expanded>span::before {
content: "\e905"; /* arrow up */
}
.sideMenuPart .navButton:hover .navButtonContent::before {

#sideMenu2 .div:hover>span::before {
color: var(--leftbar-current-bg);
}

Expand Down Expand Up @@ -295,7 +315,7 @@ th {
padding-top: 0;
}

span[data-unresolved-link].strikethrough, a.strikethrough, div.strikethrough {
span[data-unresolved-link].deprecated, a.deprecated, div.deprecated {
text-decoration: line-through;
}
.brief {
Expand Down
4 changes: 4 additions & 0 deletions scala3doc/src/dotty/dokka/DocContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ extension (r: report.type)
def warn(m: String, f: File)(using CompilerContext): Unit =
r.warning(createMessage(m, f, null), sourcePostionFor(f))

case class NavigationNode(name: String, dri: DRI, nested: Seq[NavigationNode])

case class DocContext(args: Scala3doc.Args, compilerContext: CompilerContext)
extends DokkaConfiguration:
Expand All @@ -86,6 +87,9 @@ case class DocContext(args: Scala3doc.Args, compilerContext: CompilerContext)

lazy val displaySourceSets = getSourceSets.toDisplaySourceSet

// Nasty hack but will get rid of it once we migrate away from dokka renderer
var navigationNode: Option[NavigationNode] = None

val logger = new Scala3DocDokkaLogger(using compilerContext)

lazy val staticSiteContext = args.docsRoot.map(path => StaticSiteContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ class ScalaEmbeddedResourceAppender extends PageTransformer {
"scripts/components/Input.js",
"scripts/components/FilterGroup.js",
"scripts/components/Filter.js",
"scripts/data.js",
"scripts/fast-navigation-loader.js"
"scripts/data.js"
)).asJava,
page.getChildren
)
Expand Down
23 changes: 9 additions & 14 deletions scala3doc/src/dotty/dokka/site/NavigationCreator.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dotty.dokka
package site

import org.jetbrains.dokka.base.renderers.html.{NavigationNode, NavigationPage}
import org.jetbrains.dokka.model.DPackage
import org.jetbrains.dokka.model.DModule
import org.jetbrains.dokka.pages._
Expand All @@ -11,7 +10,7 @@ import scala.collection.JavaConverters._

class NavigationCreator(using ctx: DocContext) extends PageTransformer:

private def processApiPages(pages: List[PageNode]): JList[NavigationNode] =
private def processApiPages(pages: List[PageNode]): List[NavigationNode] =
def flatMapPackages(pn: PageNode): List[NavigationNode] =
def processChildren = pn.getChildren.asScala.flatMap(flatMapPackages).toList
pn match
Expand All @@ -22,24 +21,21 @@ class NavigationCreator(using ctx: DocContext) extends PageTransformer:
case p: DPackage if p.getName == "<empty>" && p.getChildren.isEmpty =>
Nil
case p: DPackage =>
val ss = p.getSourceSets.asScala.toSet.toDisplay
List(new NavigationNode(p.getName, p.getDri, ss, JList())) ++ processChildren
List(new NavigationNode(p.getName, p.getDri, Nil)) ++ processChildren
case _: DModule =>
processChildren
case _ =>
Nil
case _ =>
Nil

pages.flatMap(flatMapPackages).sortBy(_.getName).asJava
pages.flatMap(flatMapPackages).sortBy(_.name)

private def processStaticPages(input: PageNode)(staticSiteContext: StaticSiteContext) =
def toNavigationNode(page: StaticPageNode): NavigationNode = NavigationNode(
page.title(),
page.getDri.asScala.head,
ctx.displaySourceSets,
page.getChildren.asScala
.collect { case p: StaticPageNode => toNavigationNode(p)}.asJava
page.getChildren.asScala.collect { case p: StaticPageNode => toNavigationNode(p) }.toList
)

def singleContentPage(p: PageNode) =
Expand All @@ -49,10 +45,9 @@ class NavigationCreator(using ctx: DocContext) extends PageTransformer:
if !pageRoot.getDri.contains(topLevelDri) then pageRoot
else singleContentPage(pageRoot)
val apiPages = docsRoot.getChildren.asScala.filterNot(_.isInstanceOf[StaticPageNode])
val staticPages = staticSiteContext.mainPages.map(toNavigationNode).toList.asJava
val staticPages = staticSiteContext.mainPages.map(toNavigationNode).toList
val apiNodes = processApiPages(apiPages.toList)
staticPages ++
JList(new NavigationNode("API", apiPageDRI, ctx.displaySourceSets, apiNodes))
staticPages ++ List(NavigationNode("API", apiPageDRI, apiNodes))

private def emptyNavigationJson =
val strategy = new RenderingStrategy.Write("[]")
Expand All @@ -62,11 +57,11 @@ class NavigationCreator(using ctx: DocContext) extends PageTransformer:
def defaultApiPages = processApiPages(input.getChildren.asScala.toList)
val nodes = ctx.staticSiteContext.fold(defaultApiPages)(processStaticPages(input))

val navigationPage = new NavigationPage(new NavigationNode(
summon[DocContext].navigationNode = Some(NavigationNode(
ctx.args.name,
ctx.staticSiteContext.fold(topLevelDri)(_ => docsRootDRI),
ctx.displaySourceSets,
nodes
))
val newChildren = input.getChildren ++ JList(emptyNavigationJson, navigationPage)

val newChildren = input.getChildren ++ JList(emptyNavigationJson)
input.modified(input.getName, newChildren)
31 changes: 30 additions & 1 deletion scala3doc/src/dotty/renderers/ScalaHtmlRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import org.jsoup.Jsoup
import java.nio.file.Paths

class SignatureRenderer(pageContext: ContentPage, sourceSetRestriciton: JSet[DisplaySourceSet], locationProvider: LocationProvider):
val currentDri = pageContext.getDri.asScala.head

def link(dri: DRI): Option[String] = Option(locationProvider.resolve(dri, sourceSetRestriciton, pageContext))

def renderLink(name: String, dri: DRI, modifiers: AppliedAttr*) =
Expand Down Expand Up @@ -116,6 +118,29 @@ class ScalaHtmlRenderer(using ctx: DokkaContext) extends HtmlRenderer(ctx) {
val renderer = SignatureRenderer(pageContext, sourceSets, getLocationProvider)
(renderer, new MemberRenderer(renderer, buildWithKotlinx(_, pageContext, null)))

private def buildNavigation(r: SignatureRenderer)(rootNav: NavigationNode): AppliedTag =
val currentPageDri = r.currentDri

def renderNested(nav: NavigationNode): (Boolean, AppliedTag) =
val isSelected = nav.dri == currentPageDri
def linkHtml(exapnded: Boolean = false) =
val attrs = if (isSelected) Seq(cls := "selected expanded") else Nil
a(href := r.link(nav.dri).getOrElse("#"), attrs)(nav.name)

nav.nested match
case Nil => isSelected -> div(linkHtml())
case children =>
val nested = children.map(renderNested)
val expanded = nested.exists(_._1) | nav == rootNav
val attr = if expanded || isSelected then Seq(cls := "expanded") else Nil
(isSelected || expanded) -> div(attr)(
linkHtml(expanded),
span(),
nested.map(_._2)
)

renderNested(rootNav)._2

private def buildDocumentableList(n: DocumentableList, pageContext: ContentPage, sourceSetRestriciton: JSet[DisplaySourceSet]) =
def render(n: ContentNode) = raw(buildWithKotlinx(n, pageContext, null))

Expand Down Expand Up @@ -296,6 +321,8 @@ class ScalaHtmlRenderer(using ctx: DokkaContext) extends HtmlRenderer(ctx) {
span(img(src := resolveRoot(page, s"project-logo/$fileName")))
}.toSeq

val renderer = SignatureRenderer(page.asInstanceOf[ContentPage], sourceSets, getLocationProvider)

html(
head(
meta(charset := "utf-8"),
Expand All @@ -319,7 +346,9 @@ class ScalaHtmlRenderer(using ctx: DokkaContext) extends HtmlRenderer(ctx) {
)
),
div(id := "paneSearch"),
nav(id := "sideMenu"),
nav(id := "sideMenu2")(
summon[DocContext ].navigationNode.fold("No Navigation")(buildNavigation(renderer))
),
),
div(id := "main")(
div (id := "leftToggler")(
Expand Down