Skip to content

Commit f6286f0

Browse files
authored
Merge pull request #9 from szymon-rd/scaladoc-toc-in-api
ToC in API docs
2 parents 548fa84 + 81cc947 commit f6286f0

File tree

2 files changed

+56
-28
lines changed

2 files changed

+56
-28
lines changed

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

+55-28
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ package dotty.tools.scaladoc
22
package renderers
33

44
import scala.collection.immutable.SortedMap
5-
import scala.util.chaining._
6-
import util.HTML._
7-
import scala.jdk.CollectionConverters._
5+
import scala.util.chaining.*
6+
import util.HTML.*
7+
8+
import scala.jdk.CollectionConverters.*
89
import dotty.tools.scaladoc.translators.FilterAttributes
910
import dotty.tools.scaladoc.tasty.comments.markdown.DocFlexmarkRenderer
10-
import com.vladsch.flexmark.util.ast.{Node => MdNode}
11+
import com.vladsch.flexmark.util.ast.Node as MdNode
1112
import dotty.tools.scaladoc.tasty.comments.wiki.WikiDocElement
12-
import translators._
13+
import org.jsoup.Jsoup
14+
import translators.*
1315

1416
class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) extends DocRender(signatureRenderer):
1517
import signatureRenderer._
@@ -122,8 +124,14 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
122124
Option.when(bodyContents.nonEmpty || attributes.nonEmpty)(
123125
div(cls := "cover")(
124126
div(cls := "doc")(bodyContents),
125-
Option.when(withAttributes)(h2(cls := "h500")("Attributes")).toList,
126-
dl(cls := "attributes")(attributes*)
127+
Option.when(withAttributes)(
128+
section(id := "attributes")(
129+
h2(cls := "h500")("Attributes"),
130+
dl(cls := "attributes")(attributes*)
131+
)
132+
).getOrElse(
133+
dl(cls := "attributes")(attributes*)
134+
)
127135
)
128136
)
129137
).flatten
@@ -206,20 +214,22 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
206214
private def actualGroup(name: String, members: Seq[Member | MGroup]): Seq[AppliedTag] =
207215
if members.isEmpty then Nil else
208216
div(cls := "documentableList expand")(
209-
button(cls := "icon-button show-content expand"),
210-
h3(cls := "groupHeader h200")(name),
211-
members.sortBy {
212-
case m: Member => m.name
213-
case MGroup(_, _, name) => name
214-
}.map {
215-
case element: Member =>
216-
member(element)
217-
case MGroup(header, members, _) =>
218-
div(
219-
header,
220-
members.map(member)
221-
)
222-
}
217+
section(id := name.replace(' ', '-'))(
218+
button(cls := "icon-button show-content expand"),
219+
h3(cls := "groupHeader h200")(name),
220+
members.sortBy {
221+
case m: Member => m.name
222+
case MGroup(_, _, name) => name
223+
}.map {
224+
case element: Member =>
225+
member(element)
226+
case MGroup(header, members, _) =>
227+
div(
228+
header,
229+
members.map(member)
230+
)
231+
}
232+
)
223233
) :: Nil
224234

225235
private def isDeprecated(m: Member | MGroup): Boolean = m match
@@ -371,7 +381,9 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
371381
if tabs.isEmpty then Nil else
372382
Seq(div(cls := (if singleSelection then "tabs single" else "tabs"))(
373383
div(cls := "contents")(tabs.map(t =>
374-
div(tabAttr(t.id), cls := s"tab ${t.cls}")(t.content)
384+
section(id := t.name.replace(' ', '-'))(
385+
div(tabAttr(t.id), cls := s"tab ${t.cls}")(t.content)
386+
)
375387
))
376388
))
377389

@@ -462,13 +474,28 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
462474
memberSignature(m)
463475
)
464476
)
465-
PageContent(
466-
div(
467-
intro,
468-
memberInfo(m, withAttributes = true),
477+
478+
val memberContent = div(
479+
intro,
480+
memberInfo(m, withAttributes = true),
481+
section(id := "members-list")(
469482
h2(cls := "h500")("Members list"),
470483
buildDocumentableFilter,
471484
buildMembers(m)
472-
),
473-
Seq.empty // For now, we don't support table of contents in members
485+
)
486+
)
487+
488+
val memberDocument = Jsoup.parse(memberContent.toString)
489+
490+
val toc = memberDocument.select("section[id]").asScala.toSeq
491+
.flatMap { elem =>
492+
val header = elem.selectFirst("h1, h2, h3, h4, h5, h6")
493+
Option(header).map { h =>
494+
TocEntry(h.tag().getName, h.text(), s"#${elem.id()}")
495+
}
496+
}
497+
498+
PageContent(
499+
memberContent,
500+
toc
474501
)

scaladoc/src/dotty/tools/scaladoc/util/html.scala

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ object HTML:
8888
val th = Tag("th")
8989
val tr = Tag("tr")
9090
val td = Tag("td")
91+
val section = Tag("section")
9192

9293
val cls = Attr("class")
9394
val href = Attr("href")

0 commit comments

Comments
 (0)