/* NSC -- new Scala compiler * Copyright 2007-2013 LAMP/EPFL * @author David Bernard, Manohar Jonnalagedda */ package scala package tools package nsc package doc package html import base._ import base.comment._ import model._ import scala.reflect.internal.Reporter import scala.xml.NodeSeq import scala.xml.Elem import scala.xml.dtd.DocType import scala.collection._ import java.io.Writer /** An html page that is part of a Scaladoc site. * @author David Bernard * @author Gilles Dubochet */ abstract class HtmlPage extends Page { thisPage => /** The title of this page. */ protected def title: String /** ScalaDoc reporter for error handling */ protected def docletReporter: Reporter /** The page description */ protected def description: String = // unless overwritten, will display the title in a spaced format, keeping - and . title.replaceAll("[^a-zA-Z0-9\\.\\-]+", " ").replaceAll("\\-+", " - ").replaceAll(" +", " ") /** The page keywords */ protected def keywords: String = // unless overwritten, same as description, minus the " - " description.replaceAll(" - ", " ") /** Additional header elements (links, scripts, meta tags, etc.) required for this page. */ protected def headers: NodeSeq /** The body of this page. */ def body: NodeSeq def writeFor(site: HtmlFactory) { val doctype = DocType("html") val html = { title }

{ inlineToHtml(in) }

case Title(in, 2) =>

{ inlineToHtml(in) }

case Title(in, 3) =>
{ inlineToHtml(in) }
case Title(in, _) =>
{ inlineToHtml(in) }
case Paragraph(in) =>

{ inlineToHtml(in) }

case Code(data) =>
{ SyntaxHigh(data) }
//
{ scala.xml.Text(data) }
case UnorderedList(items) => case OrderedList(items, listStyle) =>
    { listItemsToHtml(items) }
case DefinitionList(items) =>
{items map { case (t, d) =>
{ inlineToHtml(t) }
{ blockToHtml(d) }
} }
case HorizontalRule() =>
} def listItemsToHtml(items: Seq[Block]) = items.foldLeft(xml.NodeSeq.Empty){ (xmlList, item) => item match { case OrderedList(_, _) | UnorderedList(_) => // html requires sub ULs to be put into the last LI xmlList.init ++
  • { xmlList.last.child ++ blockToHtml(item) }
  • case Paragraph(inline) => xmlList :+
  • { inlineToHtml(inline) }
  • // LIs are blocks, no need to use Ps case block => xmlList :+
  • { blockToHtml(block) }
  • } } def inlineToHtml(inl: Inline): NodeSeq = inl match { case Chain(items) => items flatMap (inlineToHtml(_)) case Italic(in) => { inlineToHtml(in) } case Bold(in) => { inlineToHtml(in) } case Underline(in) => { inlineToHtml(in) } case Superscript(in) => { inlineToHtml(in) } case Subscript(in) => { inlineToHtml(in) } case Link(raw, title) => { inlineToHtml(title) } case Monospace(in) => { inlineToHtml(in) } case Text(text) => scala.xml.Text(text) case Summary(in) => inlineToHtml(in) case HtmlTag(tag) => scala.xml.Unparsed(tag) case EntityLink(target, link) => linkToHtml(target, link, hasLinks = true) } def linkToHtml(text: Inline, link: LinkTo, hasLinks: Boolean) = link match { case LinkToTpl(dtpl: TemplateEntity) => if (hasLinks) { inlineToHtml(text) } else { inlineToHtml(text) } case LinkToMember(mbr: MemberEntity, inTpl: TemplateEntity) => if (hasLinks) { inlineToHtml(text) } else { inlineToHtml(text) } case Tooltip(tooltip) => { inlineToHtml(text) } case LinkToExternal(name, url) => { inlineToHtml(text) } case _ => inlineToHtml(text) } def typeToHtml(tpes: List[model.TypeEntity], hasLinks: Boolean): NodeSeq = tpes match { case Nil => NodeSeq.Empty case List(tpe) => typeToHtml(tpe, hasLinks) case tpe :: rest => typeToHtml(tpe, hasLinks) ++ scala.xml.Text(" with ") ++ typeToHtml(rest, hasLinks) } def typeToHtml(tpe: model.TypeEntity, hasLinks: Boolean): NodeSeq = { val string = tpe.name def toLinksOut(inPos: Int, starts: List[Int]): NodeSeq = { if (starts.isEmpty && (inPos == string.length)) NodeSeq.Empty else if (starts.isEmpty) scala.xml.Text(string.slice(inPos, string.length)) else if (inPos == starts.head) toLinksIn(inPos, starts) else { scala.xml.Text(string.slice(inPos, starts.head)) ++ toLinksIn(starts.head, starts) } } def toLinksIn(inPos: Int, starts: List[Int]): NodeSeq = { val (link, width) = tpe.refEntity(inPos) val text = comment.Text(string.slice(inPos, inPos + width)) linkToHtml(text, link, hasLinks) ++ toLinksOut(inPos + width, starts.tail) } if (hasLinks) toLinksOut(0, tpe.refEntity.keySet.toList) else scala.xml.Text(string) } def typesToHtml(tpess: List[model.TypeEntity], hasLinks: Boolean, sep: NodeSeq): NodeSeq = tpess match { case Nil => NodeSeq.Empty case tpe :: Nil => typeToHtml(tpe, hasLinks) case tpe :: tpes => typeToHtml(tpe, hasLinks) ++ sep ++ typesToHtml(tpes, hasLinks, sep) } def hasPage(e: DocTemplateEntity) = { e.isPackage || e.isTrait || e.isClass || e.isObject || e.isCaseClass } /** Returns the HTML code that represents the template in `tpl` as a hyperlinked name. */ def templateToHtml(tpl: TemplateEntity, name: String = null) = tpl match { case dTpl: DocTemplateEntity => if (hasPage(dTpl)) { { if (name eq null) dTpl.name else name } } else { scala.xml.Text(if (name eq null) dTpl.name else name) } case ndTpl: NoDocTemplate => scala.xml.Text(if (name eq null) ndTpl.name else name) } /** Returns the HTML code that represents the templates in `tpls` as a list of hyperlinked names. */ def templatesToHtml(tplss: List[TemplateEntity], sep: NodeSeq): NodeSeq = tplss match { case Nil => NodeSeq.Empty case tpl :: Nil => templateToHtml(tpl) case tpl :: tpls => templateToHtml(tpl) ++ sep ++ templatesToHtml(tpls, sep) } object Image extends Enumeration { val Trait, Class, Type, Object, Package = Value } def permalink(template: Entity, isSelf: Boolean = true): Elem = def docEntityImageClass(tpl: DocTemplateEntity): String = tpl.kind + tpl.companion.fold("")("-companion-" + _.kind) def docEntityKindToCompanionTitle(ety: DocTemplateEntity, baseString: String = "See companion") = ety.companion match{ case Some(companion) => s"$baseString${ if(companion.isObject) " object" else if(companion.isTrait) " trait" else if(companion.isClass) " class" else "" }" case None => baseString } def companionAndPackage(tpl: DocTemplateEntity): NodeSeq = { tpl.companion match { case Some(companionTpl) => val objClassTrait = if (companionTpl.isObject) s"object ${tpl.name}" else if (companionTpl.isTrait) s"trait ${companionTpl.name}" else s"class ${companionTpl.name}"
    Companion {objClassTrait}
    case None => NodeSeq.Empty } }
    private def memberToUrl(template: Entity, isSelf: Boolean = true): String = { val (signature: Option[String], containingTemplate: TemplateEntity) = template match { case dte: DocTemplateEntity if (!isSelf) => (Some(dte.signature), dte.inTemplate) case dte: DocTemplateEntity => (None, dte) case me: MemberEntity => (Some(me.signature), me.inTemplate) case tpl => (None, tpl) } val templatePath = templateToPath(containingTemplate) val url = "../" * (templatePath.size - 1) + templatePath.reverse.mkString("/") url + signature.map("#" + _).getOrElse("") } }