/sbtPlugins/src/main/scala/scales/sbtplugins/SiteProject.scala
Scala | 371 lines | 226 code | 53 blank | 92 comment | 24 complexity | dfff45a5ef02db31ca192b08c9516197 MD5 | raw file
- package scales.sbtplugins
-
- import sbt._
- import FileUtilities._
- import Utils._
- import SbtWiki._
-
- trait SiteBase {
- self : MavenStyleScalaPaths =>
- /**
- * Site wide base css
- */
- def siteCSS = baseCss(this)
-
- /**
- * Site wide base jquery
- */
- def siteJQuery = resourcesOutDir(this) / "jquery-1.5.min.js"
- }
-
- trait ArtifactsHelper extends BasicManagedProject {
- self : SiteProject =>
-
- val siteArtifact = Artifact(artifactID, "zip", "zip", Some("site"), Nil, None)
- def packageSiteZip = defaultJarPath("-site.zip")
-
- val docsArtifact = Artifact(artifactID, "docs", "jar", Some("docs"),
- Nil, None)
-
- val sourceArtifact = Artifact(artifactID, "src", "jar", Some("sources"),
- Nil, None)
-
- val publishScalaDocs = true
- val publishSiteZip = true
- val publishSources = true
-
- override def artifacts =
- super.artifacts ++ {
- if (publishSiteZip) Seq( siteArtifact )
- else Seq()
- } ++ {
- if (publishScalaDocs) Seq( docsArtifact )
- else Seq()
- } ++ {
- if (publishSources) Seq( sourceArtifact )
- else Seq()
- }
-
- override def packageToPublishActions = Seq(packageSite, packageDocs, packageSrc) ++ super.packageToPublishActions
- }
-
-
- case class Copy( from : String, to : String )
- object Copy {
- def apply( from : String ) : Copy = Copy(from, from)
- }
-
- /**
- * siteDesc is a mediawiki snippet (will simply be embedded)
- * to represent the part of the site that copy refers to.
- * siteLink is optionally the target html to load for that link,
- * defaulting to copy.to / index.html.
- *
- * It MUST be in utf-8 format
- *
- * The ignore list can be tailored for just a site, it will be added to
- * the siteIgnore list upon running site.
- */
- case class Site( copy : Copy, siteDesc : String, siteLink : Option[String], ignore : Iterable[FileFilter])
- object Site{
- def apply( copy : Copy, siteDesc : String ) : Site = Site(copy,siteDesc, None, List())
-
- def apply( copy : Copy, siteDesc : String, siteLink : String ) : Site = Site(copy,siteDesc, Some(siteLink), List())
-
- def apply( copy : Copy, siteDesc : String, siteLink : Option[String] ) : Site = Site(copy,siteDesc, siteLink, List())
-
- def apply( copy : Copy, siteDesc : String, siteLink : String, ignore : Iterable[FileFilter] ) : Site = Site(copy,siteDesc, Some(siteLink), ignore)
-
- }
-
-
- /**
- * Utilities and tasks for creating a site
- */
- trait SiteProject extends BasicScalaProject with DocWrapper with SiteBase with ArtifactsHelper {
-
- val xraySite = Site(Copy("classes.sxr"), "Scala XRay Specs view of the source, also available via the Scaladocs")
- val docsSite = Site(Copy("doc/main/api", "doc"), "ScalaDocs for ${artifactID}")
- val xrayTestsSite = Site(Copy("test-classes.sxr"), "Scala XRay Specs view of the test source")
- val scctSite = Site(Copy("coverage-report"), "SCCT - Scala TestCoverage")
- // here we don't have an index just the dir
- val surefireRepSite = Site(Copy("surefire-reports"), "Surefire Reports", "surefire-reports/")
- val testReviewSite = Site(Copy("test-review"), "Test Review Results")
-
- def sites = List(xraySite, docsSite, xrayTestsSite, scctSite, surefireRepSite, testReviewSite)
-
- lazy val packageSite = packageSiteAction
- def packageSiteAction = zipTask(siteOutputPath ** "*", packageSiteZip).dependsOn(site)
-
- lazy val sitePublishRelative = getSitePublishRelative
- // by default we don't want the release to show any intermediate builds for the docs
- def getSitePublishRelative = projectOrganization.value +"/"+ artifactID +"/"+ (projectVersion.value.toString.replaceAll("-.*",""))
-
- // paths don't like relatives and forward slashes
- lazy val siteDeployFile = getSiteDeployFile
- def getSiteDeployFile = new java.io.File("./../sites").getAbsoluteFile()
-
- /**
- * List of files to ignore when deploying the site, defaults to siteIgnore
- */
- def deploySiteIgnore = siteIgnore
-
- /**
- * Deploys the zip file with a locally useable site and the remote with further changed paths
- */
- lazy val deploySite = deploySiteAction
- def deploySiteAction = task {
- // make dirs, copy over the site then zip
- import FileUtilities._
- import java.io.File
- val dir = new File(siteDeployFile, sitePublishRelative).getCanonicalFile
- val parent = dir.getParentFile
- val sitesrc = siteOutputPath.asFile
- val sitezip = packageSiteZip.asFile.getCanonicalFile
- println("Attempting to publish from "+sitesrc.getCanonicalPath+" with zip "+sitezip.getCanonicalPath)
-
- copyDir(sitesrc, dir, deploySiteIgnore, log) ~~>
- copyFile(sitezip, new File(dir, sitezip.getName), log)
- } dependsOn(packageSite)
-
- /**
- * Override to change the tasks executed before the site is run.
- */
- def siteAllActions = "clean;test-coverage;test-review;doc"
-
- def canFailActions = List("test-coverage","test-review")
-
- def ignoreFailActionsForSite = true
-
- lazy val siteAll = siteAllAction
- def siteAllAction = task {
- callCommands(siteAllActions+";site", this, if (ignoreFailActionsForSite) canFailActions else Nil)
- }
-
- lazy val siteResource = siteResourceDir
- def siteResourceDir = sourcePath / "site"
-
- def siteIndexHeader = siteResourceDir / "siteIndexHeader.mw"
- def siteIndexFooter = siteResourceDir / "siteIndexFooter.mw"
-
- val userF = ()=>{
- var env = System.getenv("USERNAME")
- if (env eq null)
- env = System.getenv("USER")
- if (env eq null)
- "Unknown User"
- else
- env
- }
-
- val sysEnv = {
- import scala.collection.jcl.Conversions._
- System.getenv().map{(x) => (x._1, () => x._2)}
- }
- val sysProperties = {
- import scala.collection.jcl.Conversions._
- System.getProperties().map{(x) => (x._1.toString, () => x._2.toString)}
- }
-
- /**
- * Override to change the pre code end for cend tokens
- */
- def cend() = () => "</pre>"
-
- /**
- * Override to change the code@lang pre for cXX tokens
- */
- def cbs(lang : String) = () => "<pre class=\"language-"+lang+"\">"
-
- def siteTokens = Map[String, ()=>String]( "User" -> userF, "timestamp" -> { () => {new java.util.Date().toString}},
- "datetime" -> {() => {java.text.DateFormat.getDateTimeInstance.format(new java.util.Date())}},
- "artifactID" -> {() => artifactID},
- "projectName" -> {() => projectName.value},
- "projectVersion" -> {() => projectVersion.value.toString},
- "projectOrganization" -> {() => projectOrganization.value},
- "projectOrganisation" -> {() => projectOrganization.value},
- "FullVersion" -> {() => projectOrganization.value+ " : " + artifactID + "-" + projectVersion.value.toString},
- "cscala" -> cbs("scala"),
- "bxml" -> (() => "<code class=\"xml\">"),
- "cxml" -> cbs("xml"),
- "exml" -> (() => "</code>"),
- "cjava" -> cbs("java"),
- "cend" -> cend()
- ) ++ sysEnv ++ sysProperties
-
- /**
- * By default deletes markup files after calling site-docs
- */
- val siteMarkupDelete = true
-
- /**
- * Override to change/disable the use of highlight.
- *
- * NOTE: It does some crazy looking stuff in here, but its
- * due to bugs in <IE9 that strip newlines out of pre's.
- * The outerHTML trick gets around that limitation.
- *
- * In both cases we wrap a code in the middle, letting highlight.js do its
- * thing.
- */
- def highlightScripts =
- js("./highlight/highlight.pack.js") +
- """<script type="text/javascript">
- $(function() {
- $("pre[class^='language-']").each(function(i,elem) {
- var clazz = $(elem).attr('class');
- var str = elem.innerHTML//.replace(/\r\n|\r|\n/g,"<br/>");
- // Workaround for IE <PRE> innerHTML normalization quirk
- if (elem.tagName == "PRE" && "outerHTML" in elem)
- {
- elem.outerHTML = "<PRE><CODE class='"+clazz+"'>" + str + "</CODE></PRE>";
- }
- else
- {
- elem.innerHTML = "<CODE class='"+clazz+"'>" + str + "</CODE>"; //.replace(/\r\n|\r|\n/g,"<br/>");;
- }
- });
- hljs.initHighlighting();
- });
- </script>
- """
- /**
- * String representing the headers for each generated site html.
- *
- * Defaults to the site wide CSS, includes a jquery (override siteJQuery to change versions etc) and adds highlight.js (override sitHightlightStyle to change the style used). NOTE as a default only xml, java and scala are provided
- */
- def siteHeaders = css("./scales_base.css") + css("./site_docs.css") + siteHighlightStyle + js("./jquery.js") + highlightScripts
-
- def siteMediaWikiTemplates : List[(String, String)] = List(("code","""<code class="{{{lang}}}"><pre>{{{2}}}</pre></code>"""));
-
- /**
- * Override to change the highlight style used during the site-docs run.
- */
- def siteHighlightStyle = css("./highlight/styles/idea.css")
-
- /**
- * List of files to ignore when generating the site docs, defaults to siteIgnore
- */
- def siteDocsIgnore = siteIgnore
-
- /**
- * Generates user documentation from the
- * src/site directory (configure with siteDocsBase).
- * Whatever is in there is copied to target and all known markup
- * extensions are converted.
- *
- * Note by default it will delete all original markup
- * files after conversion.
- * Use siteMarkupDelete to control this behaviour.
- *
- */
- lazy val siteDocs = siteDocsAction
- def siteDocsAction = task { // TODO - allow the source zip for highlighting and site_docs to be replaced
- ( if (siteResourceDir.exists) None else Some("The site directory "+siteResourceDir+" does not exist, please create it, or override siteResourceDir before calling site.") ) ~~>
- unpackResources(this) ~~>
- FileUtilities.copyFile(siteCSS, siteOutputPath / "scales_base.css", log) ~~>
- FileUtilities.copyFile(siteJQuery, siteOutputPath / "jquery.js", log) ~~>
- FileUtilities.copyFile(resourcesOutDir(this)./("site_docs.css"), siteOutputPath / "site_docs.css", log) ~~>
- {FileUtilities.unzip(resourcesOutDir(this)./("highlight.zip"), siteOutputPath, log);None } ~~>
- SbtWiki.templates.withValue(siteMediaWikiTemplates) {
- copyAndConvert(siteResourceDir, siteOutputPath, siteDocsIgnore,
- siteHeaders, siteTokens, log, siteMarkupDelete, siteMarkupDocHeaders)
- }
- }
-
- /**
- * A list of markup docs that will be shown in the index.
- * The pair is relative filename without extension -> description.
- */
- val siteMarkupDocs : List[(String, String)]
-
- /**
- * Users wishing to add a title or override other headers should
- * add their markup document here, relative filename to MarkupHeader
- */
- def siteMarkupDocHeaders : Map[String, MarkupHeader] =
- Map[String, MarkupHeader]()
-
- /**
- * List of files to ignore when building a site
- */
- def siteIgnore : Iterable[FileFilter] = List(new ExactFilter(siteIndexHeader.name), new ExactFilter(siteIndexFooter.name), new ExactFilter(".svn"), // all svn files
- GlobFilter("*.*~")) // all emacs backups
-
- lazy val site = siteAction
- def siteAction = task {
- import FileUtilities._
- // create target dir
- val outDir = siteOutputPath
- val siteIndex = outDir / "index.html"
- val siteIndexMd = outDir / "index.mw"
- val siteIndexMdf = siteIndexMd.asFile
-
- val siteIgnores = siteIgnore
-
- // doesn't matter if it fails
- createDirectory(outDir, log)
-
- val sitesc = sites
- // copy them over
- sitesc.foldLeft( None : Option[String]){
- (x, y) =>
- x ~~> {
- val from = new java.io.File(outputPath.asFile, y.copy.from)
- val to = new java.io.File( outDir.asFile, y.copy.to)
- if (from.exists)
- copyDir(from, to, siteIgnores ++ y.ignore, log)
- else {
- log.debug("Could not find directory "+from.getAbsolutePath+" skipping copy")
- None
- }
- }
- } ~~> {
- // create cover page..
- val wikiBase = if (siteIndexHeader.exists) readString(siteIndexHeader.asFile, utf8, log)
- else Right("= ${FullVersion} Site =\n")
- wikiBase.fold(Some(_),{b => write(siteIndexMdf, b+"\n<br/>\n", utf8, log) ~~> {
- // middle
- sitesc.foldLeft( None : Option[String] ){
- (x,y) =>
- x ~~> {
- if (new java.io.File(outputPath.asFile, y.copy.from).exists) {
- val link = y.siteLink.getOrElse{"./"+y.copy.to+"/index.html"}
- append(siteIndexMdf, "* ["+link+" "+y.siteDesc+"]\n", utf8, log)
- } else x
- }
- } ~~> (
- if (siteMarkupDocs.size > 0) {
- append(siteIndexMdf, "\n<br/>\n== Project Documentation ==\n<br/>\n", utf8, log)
- siteMarkupDocs.foldLeft( None : Option[String] ){
- (x,y) =>
- x ~~> {
- val f = new java.io.File(outDir.asFile, y._1 + ".html")
- if (f.exists) {
- append(siteIndexMdf, "* [./"+y._1+".html "+y._2+"]\n", utf8, log)
- } else Some("File "+f.getCanonicalPath + " does not exist")
- }
- }
- } else None
- ) ~~> {
- // footer
- val wikiEnd = if (siteIndexFooter.exists) readString(siteIndexFooter.asFile, utf8, log)
- else Right("<br/>\n[./"+packageSiteZip.name+" Download Site Zip]\n\nBuilt By: ${User}, ${timestamp}")
- wikiEnd.fold(Some(_),{f=>append(siteIndexMdf, f, utf8, log)})
- }
- }}) ~~> {
- // convert to html
- try{
- unpackResources(this) ~~>
- FileUtilities.copyFile(siteCSS, outDir / "scales_base.css", log) ~~>
- convert(siteIndexMd, siteIndex, title("${FullVersion} Site") + siteHeaders, siteTokens, log)
- } catch {
- case e : Exception => Some(e.getMessage)
- }
- }
- }
- } dependsOn siteDocs
-
- def siteOutputPath = outputPath / "site"
-
- }