Skip to content

Commit

Permalink
Docs: auto-generate /index.html from <version>/docs/home.html and add…
Browse files Browse the repository at this point in the history
… version selection
  • Loading branch information
harrah committed Oct 16, 2012
1 parent 0ea5965 commit 600caef
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 6 deletions.
63 changes: 61 additions & 2 deletions project/Docs.scala
Expand Up @@ -12,10 +12,16 @@
object Docs
{
val cnameFile = SettingKey[File]("cname-file", "Location of the CNAME file for the website.")
val SnapshotPath = "snapshot"
val ReleasePath = "release"
val DocsPath = "docs"
val IndexHtml = "index.html"
val HomeHtml = "home.html"
val VersionPattern = """(\d+)\.(\d+)\.(\d+)(-.+)?""".r.pattern

def settings: Seq[Setting[_]] =
site.settings ++
site.sphinxSupport("docs") ++
site.sphinxSupport(DocsPath) ++
site.includeScaladoc("api") ++
siteIncludeSxr("sxr") ++
ghPagesSettings
Expand All @@ -41,10 +47,25 @@ object Docs
IO.copy(mappings map { case (file, target) => (file, versioned / target) })
IO.copyFile(cname, repo / cname.getName)
IO.touch(repo / ".nojekyll")
linkSite(repo, v, if(snap) "snapshot" else "release", s.log)
IO.write(repo / "versions.js", versionsJs(sortVersions(collectVersions(repo))))
if(!snap)
RootIndex(versioned / DocsPath / "home.html", repo / IndexHtml)
linkSite(repo, v, if(snap) SnapshotPath else ReleasePath, s.log)
s.log.info("Copied site to " + versioned)
repo
}
def versionsJs(vs: Seq[String]): String = "var availableDocumentationVersions = " + vs.mkString("['", "', '", "']")
// names of all directories that are explicit versions
def collectVersions(base: File): Seq[String] = (base * versionFilter).get.map(_.getName)
def sortVersions(vs: Seq[String]): Seq[String] = vs.sortBy(versionComponents).reverse
def versionComponents(v: String): Option[(Int,Int,Int,Option[String])] = {
val m = VersionPattern.matcher(v)
if(m.matches())
Some( (m.group(1).toInt, m.group(2).toInt, m.group(3).toInt, Option(m.group(4))) )
else
None
}
def versionFilter = new PatternFilter(VersionPattern) && DirectoryFilter

def linkSite(base: File, to: String, from: String, log: Logger) {
val current = base / to
Expand All @@ -60,4 +81,42 @@ object Docs
case 0 => ()
case code => error("Could not create symbolic link '" + file.getAbsolutePath + "' with path " + path)
}
}
object RootIndex
{
import Docs._
import org.jsoup._

def apply(versionIndex: File, to: File)
{
val doc = Jsoup.parse(versionIndex, "UTF-8")
rewriteLinks(doc)
removeSearch(doc)
IO.write(to, doc.outerHtml)
}
def retargetIndexLink(original: String): String =
if(isAbsolute(original) || original.startsWith("#"))
original
else
ReleasePath + "/docs/" + original

def isAbsolute(s: String): Boolean = (new java.net.URI(s)).isAbsolute

def rewriteLinks(doc: nodes.Document)
{
rewriteLinks(doc, "*", "href")
rewriteLinks(doc, "script", "src")
}
def rewriteLinks(doc: nodes.Document, elemName: String, attrName: String): Unit =
for(elem <- select(doc, elemName + "[" + attrName + "]"))
elem.attr(attrName, retargetIndexLink(elem.attr(attrName)))

def removeSearch(doc: nodes.Document): Unit =
doc.select(".search").remove()

def select(doc: nodes.Document, s: String) =
{
import collection.JavaConverters._
doc.select(s).iterator.asScala
}
}
5 changes: 4 additions & 1 deletion project/p.sbt
@@ -1,4 +1,7 @@
libraryDependencies += "net.databinder" %% "dispatch-http" % "0.8.8"
libraryDependencies ++= Seq(
"net.databinder" %% "dispatch-http" % "0.8.8",
"org.jsoup" % "jsoup" % "1.7.1"
)

addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.6.0")

Expand Down
6 changes: 3 additions & 3 deletions src/sphinx/_sphinx/themes/sbt/layout.html
Expand Up @@ -6,6 +6,8 @@

{% extends "basic/layout.html" %}

{% set script_files = script_files + ['../../versions.js'] %}
{% set script_files = script_files + ['_static/set-versions.js'] %}

{% set css_files = css_files + ['_static/base.css'] %}
{% set css_files = css_files + ['_static/docs.css'] %}
Expand Down Expand Up @@ -73,7 +75,7 @@
{%- endif %}
</li>
<li>
Version {{ release|e }}
<select id="versions"><option selected value="{{release}}">Version {{ release|e }}</option></select>
</li>
</ul>
</div>
Expand All @@ -99,5 +101,3 @@
</div>
{% block footer %}{% endblock %}
{% endblock %}


12 changes: 12 additions & 0 deletions src/sphinx/_sphinx/themes/sbt/static/docs.css
Expand Up @@ -208,3 +208,15 @@ input#submit-search {
input#search-input {
margin: 0px;
}
.breadcrumb li select {
width: auto;
height: auto;
background-color: rgba(242, 242, 235, 0.1);
border: 1px solid rgba(204, 204, 204, 0.5);
padding: 1px;
margin: -2px 0px 0px;
font-weight: bold;
}
.breadcrumb li select option {
font-weight: normal;
}
60 changes: 60 additions & 0 deletions src/sphinx/_sphinx/themes/sbt/static/set-versions.js
@@ -0,0 +1,60 @@
$(document).ready(function() {
// array of versions provided by short js file in root so that
// old documentation versions do not need to be
var versions = availableDocumentationVersions;
var releasePath = 'release/';
var snapshotPath = 'snapshot/';
var docsPath = "docs/";

// get the version drop-down
var select = $("#versions");
// the currently selected value is the current version
var selected = select.val();
// clear the options, which should only include the current version
select.html('');

// populate the options with the latest list of versions
for(var i = 0; i < versions.length; i++) {
var v = versions[i];
var sel = '';
if (v == selected) sel = 'selected ';
select.append('<option ' + sel + 'value="' + v + '">Version ' + v + '</option>');
}

// check if primary exists, go there if it does, or go to fallback if it does not
var gotoIfExists = function(primary, fallback) {
$.ajax({
type: 'HEAD',
url: primary,
success: function() { document.location.href = primary },
error: function() { document.location.href = fallback },
});
};

// return a new URL String with its path transformed by function f: String => String
var mapPath = function(urlString, f) {
var u = document.createElement('a');
u.href = urlString;
u.pathname = f(u.pathname);
return u.href;
};

// when an option is selected, switch to that version of the current page,
// but if it doesn't exist, go to the index for that version
select.change(function() {
var newV = $(this).val();
var oldLoc = document.location.href;

var changeVersion = function(oldPathname) {
var newPath = newV + '/';
var changed = oldPathname.replace(selected + '/', newPath).replace(snapshotPath, newPath).replace(releasePath, newPath);
// This occurs for unversioned files, specifically /index.html.
// Redirect to the versioned path in this case (won't work when previewing on the local filesytem)
if (changed == oldPathname) changed = newPath + docsPath + changed;
return changed;
};
var home = function(pathname) { return 'index.html'; };

gotoIfExists( mapPath(oldLoc, changeVersion), mapPath(oldLoc, home));
});
});

0 comments on commit 600caef

Please sign in to comment.