summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-02-19 17:18:27 +0100
committerFelix Mulder <felix.mulder@gmail.com>2016-02-26 18:55:15 +0100
commit89cd6a308ed39b0b0af24773ce5d68e3f16efe03 (patch)
tree861096fa71cc4b5037c42f94390177f5f1328d48
parente891bb60f721465bfe497b16f5ef440de0a7d5e5 (diff)
downloadscala-89cd6a308ed39b0b0af24773ce5d68e3f16efe03.tar.gz
scala-89cd6a308ed39b0b0af24773ce5d68e3f16efe03.tar.bz2
scala-89cd6a308ed39b0b0af24773ce5d68e3f16efe03.zip
Add package view to scaladoc
The package view shows the current package's: - siblings - children packages - path to root package - child entities (objects, traits, abstract types and classes)
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala95
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.css124
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js3
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css4
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js6
-rw-r--r--test/scaladoc/scalacheck/HtmlFactoryTest.scala5
6 files changed, 221 insertions, 16 deletions
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
index 969e19c770..861dccc5dd 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
@@ -71,9 +71,74 @@ trait EntityPage extends HtmlPage {
<div id="member-results"></div>
</div>
</div>
- <div id="content-container" style="-webkit-overflow-scrolling: touch;">
- <div id="content">
- { content }
+ <div id="content-scroll-container" style="-webkit-overflow-scrolling: touch;">
+ <div id="content-container" style="-webkit-overflow-scrolling: touch;">
+ <div id="subpackage-spacer">
+ <div id="packages">
+ <h1>Packages</h1>
+ <ul>
+ {
+ def entityToUl(mbr: TemplateEntity with MemberEntity, indentation: Int): NodeSeq =
+ <li class={"current-entities indented" + indentation}>
+ {
+ mbr match {
+ case dtpl: DocTemplateEntity =>
+ dtpl.companion.fold(<span class="separator"></span>) { c: DocTemplateEntity =>
+ <a class="object" href={relativeLinkTo(c)} title={c.comment.fold("")(com => inlineToStr(com.short))}></a>
+ }
+ case _ => <span class="separator"></span>
+ }
+ }
+ <a class={mbr.kind} href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => inlineToStr(com.short))}></a>
+ <a href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => inlineToStr(com.short))}>
+ {mbr.name}
+ </a>
+ </li>
+
+ // Get path from root
+ val rootToParentLis = tpl.toRoot
+ .tail
+ .reverse
+ .zipWithIndex
+ .map { case (pack, ind) =>
+ memberToHtml(pack, tpl, indentation = ind, isParent = (pack eq tpl.toRoot.tail.head))
+ }
+
+ val parent = tpl.toRoot match {
+ case _ :: parent :: _ if !parent.isRootPackage => Some(parent)
+ case _ => None
+ }
+
+ val parentSub = parent.fold(Seq[TemplateEntity with MemberEntity](tpl)) { p =>
+ p.templates.filter(_.isPackage).sortBy(_.name)
+ }
+
+ // If current entity is a package, take its containing entities - otherwise take parent's containing entities
+ val currentPackageTpls =
+ if (tpl.isPackage) tpl.templates
+ else parent.fold(Seq.empty[TemplateEntity with MemberEntity])(p => p.templates)
+
+ val (subsToTpl, subsAfterTpl) = parentSub.partition(_.name <= tpl.name)
+
+ val subsToTplLis = subsToTpl.map(memberToHtml(_, tpl, indentation = rootToParentLis.length))
+ val subsAfterTplLis = subsAfterTpl.map(memberToHtml(_, tpl, indentation = rootToParentLis.length))
+ val currEntityLis = currentPackageTpls
+ .filter(x => !x.isPackage && (x.isTrait || x.isClass || x.isAbstractType))
+ .sortBy(_.name)
+ .map(entityToUl(_, rootToParentLis.length + 1))
+ val currSubLis = tpl.templates
+ .filter(_.isPackage)
+ .sortBy(_.name)
+ .map(memberToHtml(_, tpl, indentation = rootToParentLis.length + 1))
+
+ rootToParentLis ++ subsToTplLis ++ currEntityLis ++ currSubLis ++ subsAfterTplLis
+ }
+ </ul>
+ </div>
+ </div>
+ <div id="content">
+ { content }
+ </div>
</div>
</div>
</body>
@@ -146,7 +211,6 @@ trait EntityPage extends HtmlPage {
<div id="definition">
{
val (src, alt) = docEntityKindToBigImage(tpl)
-
val identifier = alt.toString.substring(0,2).toLowerCase
tpl.companion match {
@@ -154,7 +218,8 @@ trait EntityPage extends HtmlPage {
<a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><div class={s"big-circle companion $identifier"}>{ identifier.substring(0,1) }</div></a>
case _ =>
<div class={ "big-circle " + alt.toString.toLowerCase }>{ identifier.substring(0,1) }</div>
- }}
+ }
+ }
{ owner }
<h1>{ displayName }</h1>{
if (tpl.isPackage) NodeSeq.Empty else <h3>{companionAndPackage(tpl)}</h3>
@@ -262,7 +327,13 @@ trait EntityPage extends HtmlPage {
{ if (concValueMembers.isEmpty) NodeSeq.Empty else
<div class="values members">
<h3>{ if (absValueMembers.isEmpty) "Value Members" else "Concrete Value Members" }</h3>
- <ol>{ concValueMembers map (memberToHtml(_, tpl)) }</ol>
+ <ol>
+ {
+ concValueMembers
+ .filter(_.kind != "package")
+ .map(memberToHtml(_, tpl))
+ }
+ </ol>
</div>
}
@@ -336,7 +407,12 @@ trait EntityPage extends HtmlPage {
</body>
}
- def memberToHtml(mbr: MemberEntity, inTpl: DocTemplateEntity): NodeSeq = {
+ def memberToHtml(
+ mbr: MemberEntity,
+ inTpl: DocTemplateEntity,
+ isParent: Boolean = false,
+ indentation: Int = 0
+ ): NodeSeq = {
// Sometimes it's same, do we need signatureCompat still?
val sig = if (mbr.signature == mbr.signatureCompat) {
<a id={ mbr.signature }/>
@@ -346,6 +422,7 @@ trait EntityPage extends HtmlPage {
val memberComment = memberToCommentHtml(mbr, inTpl, isSelf = false)
<li name={ mbr.definitionName } visbl={ if (mbr.visibility.isProtected) "prt" else "pub" }
+ class={ s"indented$indentation " + (if (mbr eq inTpl) "current" else "") }
data-isabs={ mbr.isAbstract.toString }
fullComment={ if(memberComment.filter(_.label=="div").isEmpty) "no" else "yes" }
group={ mbr.group }>
@@ -828,7 +905,9 @@ trait EntityPage extends HtmlPage {
}
}
if (!nameLink.isEmpty)
- <a href={nameLink}>{nameHtml}</a>
+ <a title={mbr.comment.fold("")(c => inlineToStr(c.short))} href={nameLink}>
+ {nameHtml}
+ </a>
else nameHtml
}{
def tparamsToHtml(mbr: Any): NodeSeq = mbr match {
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.css
index ea1c358149..cb11df3011 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.css
@@ -393,7 +393,7 @@ div#search-progress > div#progress-fill {
color: #bbb;
}
-div#content-container {
+div#content-scroll-container {
position: absolute;
top: 0;
right: 0;
@@ -404,14 +404,130 @@ div#content-container {
overflow-y: auto;
}
+div#content-container {
+ max-width: 1140px;
+ margin: 0 auto;
+}
+
div#content-container > div#content {
-webkit-overflow-scrolling: touch;
display: block;
overflow-y: auto;
- max-width: 1140px;
margin: 5em auto 0;
}
+div#content-container > div#subpackage-spacer {
+ float: right;
+ height: 100%;
+ margin: 0.5rem 0.5rem 0 0.5em;
+ font-size: 0.8em;
+}
+
+div#packages > h1 {
+ color: #103a51;
+}
+
+div#packages > ul {
+ list-style-type: none;
+}
+
+div#packages > ul > li {
+ position: relative;
+ margin: 0.5rem 0;
+ width: 100%;
+ border-radius: 0.2em;
+ min-height: 1.5em;
+ padding-left: 2em;
+}
+
+div#packages > ul > li.current:hover {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ cursor: pointer;
+}
+
+div#packages > ul > li > *:nth-child(1),
+div#packages > ul > li > *:nth-child(2) {
+ float: left;
+ display: inline;
+ height: 1em;
+ width: 1em;
+ margin: 2px 0 0;
+ cursor: pointer;
+}
+
+div#packages > ul > li > a.class {
+ background: url("class.svg") no-repeat center;
+ background-size: 0.9em;
+}
+
+div#packages > ul > li > a.trait {
+ background: url("trait.svg") no-repeat center;
+ background-size: 0.9em;
+}
+
+div#packages > ul > li > a.object {
+ background: url("object.svg") no-repeat center;
+ background-size: 0.9em;
+}
+
+div#packages > ul > li > a.abstract.type {
+ background: url("abstract_type.svg") no-repeat center;
+ background-size: 0.9em;
+}
+
+div#packages > ul > li > a {
+ text-decoration: none !important;
+ margin-left: 0.1em;
+}
+
+/* Indentation levels for packages */
+div#packages > ul > li.indented0 { padding-left: 0em; }
+div#packages > ul > li.indented1 { padding-left: 1em; }
+div#packages > ul > li.indented2 { padding-left: 2em; }
+div#packages > ul > li.indented3 { padding-left: 3em; }
+div#packages > ul > li.indented4 { padding-left: 4em; }
+div#packages > ul > li.indented5 { padding-left: 5em; }
+div#packages > ul > li.indented6 { padding-left: 6em; }
+div#packages > ul > li.indented7 { padding-left: 7em; }
+div#packages > ul > li.indented8 { padding-left: 8em; }
+div#packages > ul > li.indented9 { padding-left: 9em; }
+div#packages > ul > li.indented10 { padding-left: 10em; }
+div#packages > ul > li.current.indented0 { padding-left: -0.5em }
+div#packages > ul > li.current.indented1 { padding-left: 0.5em }
+div#packages > ul > li.current.indented2 { padding-left: 1.5em }
+div#packages > ul > li.current.indented3 { padding-left: 2.5em }
+div#packages > ul > li.current.indented4 { padding-left: 3.5em }
+div#packages > ul > li.current.indented5 { padding-left: 4.5em }
+div#packages > ul > li.current.indented6 { padding-left: 5.5em }
+div#packages > ul > li.current.indented7 { padding-left: 6.5em }
+div#packages > ul > li.current.indented8 { padding-left: 7.5em }
+div#packages > ul > li.current.indented9 { padding-left: 8.5em }
+div#packages > ul > li.current.indented10 { padding-left: 9.5em }
+
+div#packages > ul > li.current > span.symbol {
+ border-left: 0.25em solid #72D0EB;
+ padding-left: 0.25em;
+}
+
+div#packages > ul > li > span.symbol > a {
+ text-decoration: none;
+}
+
+div#packages > ul > li > span.symbol > span.name {
+ font-weight: normal;
+}
+
+div#packages > ul > li .fullcomment,
+div#packages > ul > li .modifier_kind,
+div#packages > ul > li .permalink,
+div#packages > ul > li .shortcomment {
+ display: none;
+}
+
div#search-results {
color: #103a51;
position: absolute;
@@ -710,6 +826,10 @@ only screen /* iPhone 6 */
and (max-device-width: 667px)
and (-webkit-device-pixel-ratio: 2)
{
+ div#content-container > div#subpackage-spacer {
+ display: none;
+ }
+
div#content-container > div#content {
margin: 3.3em auto 0;
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
index caa6406bc5..494ad91cc8 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -98,7 +98,7 @@ function handleKeyNavigation() {
scroller.scrollDown = function($elem) {
var yPos = $elem.offset().top; // offset relative to viewport
- if ($container.height() < yPos) {
+ if ($container.height() < yPos || (yPos - $("#search").height()) < 0) {
$container.animate({
scrollTop: $container.scrollTop() + yPos - $("#search").height() - 10
}, 200);
@@ -132,6 +132,7 @@ function handleKeyNavigation() {
var $old = items.next();
$old.addClass("selected");
+ scroller.scrollDown($old);
$(window).bind("keydown", function(e) {
switch ( e.keyCode ) {
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
index 2265f8f045..1827868171 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -133,6 +133,10 @@ body.trait div#definition {
padding-left: 0;
}
+span.symbol > a {
+ display: inline-block;
+}
+
#signature > span.symbol {
text-align: left;
display: inline;
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
index b0719b1ed5..ebffe81490 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -27,6 +27,12 @@ $(document).ready(function() {
}
});
+ var oldWidth = $("div#subpackage-spacer").width() + 1 + "px";
+ $("div#packages > ul > li.current").click(function() {
+ $("div#subpackage-spacer").css({ "width": oldWidth });
+ $("li.current-entities").toggle();
+ });
+
var controls = {
visibility: {
publicOnly: $("#visbl").find("> ol > li.public"),
diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
index daa7de8545..3fe5ef3baf 100644
--- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala
+++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
@@ -797,11 +797,6 @@ object Test extends Properties("HtmlFactory") {
case _ => false
}
- property("SI-8144: Members' permalink - package") = check("some/index.html") { node =>
- ("type link" |: node.assertTypeLink("../some/index.html")) &&
- ("member: some.pack" |: node.assertValuesLink("some.pack", "../some/index.html#pack"))
- }
-
property("SI-8144: Members' permalink - inner package") = check("some/pack/index.html") { node =>
("type link" |: node.assertTypeLink("../../some/pack/index.html")) &&
("member: SomeType (object)" |: node.assertValuesLink("some.pack.SomeType", "../../some/pack/index.html#SomeType")) &&