Skip to content

Commit

Permalink
Improved json-multi output: TypeEntities as HTML, better page-mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
szeiger committed Oct 4, 2010
1 parent f0a3553 commit f9759a3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 30 deletions.
Expand Up @@ -7,9 +7,10 @@ import comment._
import java.io.{PrintStream, FileOutputStream, BufferedOutputStream, StringWriter, File => JFile}
import scala.collection._

abstract class AbstractJsonFactory {
abstract class AbstractJsonFactory { self =>

val doInline = true
val typeEntitiesAsHtml = false

def prepareModel(universe: Universe) = {
println("Building JSON model")
Expand All @@ -29,6 +30,7 @@ abstract class AbstractJsonFactory {
val allModels = new mutable.HashMap[Int, JBase]
val allModelsReverse = new mutable.HashMap[JBase, Int]
val builder = new JsonBuilder[Link] {
val typeEntitiesAsHtml = self.typeEntitiesAsHtml
def global[T <: Entity](e: T)(f: T => JBase) = globalEntityOrdinals.get(EntityHash(e)) match {
case Some(ord) => Link(ord)
case None =>
Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/com/novocode/extradoc/json/JBase.scala
Expand Up @@ -4,7 +4,7 @@ import scala.tools.nsc.doc._
import model._
import comment._

import java.io.Writer
import java.io.{Writer, StringWriter}
import scala.collection._

abstract class CanBeValue[-T] {
Expand Down Expand Up @@ -59,6 +59,11 @@ sealed abstract class JBase {
f(this)
children foreach { _.foreachRec(f) }
}
override def toString = {
val wr = new StringWriter
writeTo(wr, {_.target})
wr.toString
}
}

object JBase {
Expand Down
38 changes: 29 additions & 9 deletions src/main/scala/com/novocode/extradoc/json/JsonBuilder.scala
Expand Up @@ -5,10 +5,12 @@ import model._
import comment._

import scala.collection._
import scala.xml.{Xhtml, NodeSeq}
import scala.xml.{Xhtml, NodeSeq, NodeBuffer, Text, Elem}

abstract class JsonBuilder[Link : CanBeValue] {

val typeEntitiesAsHtml: Boolean

def global[T <: Entity](e: T)(f: T => JBase): Link

def as[T](o: AnyRef)(f: T => Unit)(implicit m: ClassManifest[T]): Unit =
Expand Down Expand Up @@ -76,20 +78,38 @@ abstract class JsonBuilder[Link : CanBeValue] {

def createTypeEntity(t: TypeEntity): JObject = {
val j = new JObject
j += "name" -> t.name
j +?= "refEntity" -> JObject(t.refEntity.map {
case (k,v) =>
val vv = new JObject
vv += "e" -> global(v._1)(createEntity _)
vv += "l" -> v._2
k.toString -> vv
})
if(typeEntitiesAsHtml) {
val b = new NodeBuffer
val links = new mutable.ArrayBuffer[Link]
val name = t.name
var pos = 0
t.refEntity foreach { case (start, (ref, len)) =>
if(pos < start) b += Text(name.substring(pos, start))
links += global(ref)(createEntity _)
b += Elem(null, "a", null, xml.TopScope, Text(name.substring(start, start+len)))
pos = start+len
}
if(pos < name.length-1) b += Text(name.substring(pos))
j += "_xname" -> Xhtml.toXhtml(b)
j +?= "_refs" -> JArray(links)
} else {
j += "name" -> t.name
j +?= "refEntity" -> JArray(t.refEntity.map {
case (k,v) =>
val vv = new JObject
vv += "s" -> k
vv += "l" -> v._2
vv += "e" -> global(v._1)(createEntity _)
vv
})
}
j
}

def createEntity(e: Entity): JObject = {
val j = new JObject
j += "inTemplate" -> global(e.inTemplate)(createEntity _)
// "toRoot" is own ID plus recursively toRoot of inTemplate
//j += "toRoot" -> JArray(e.toRoot.map(e => global(e)(createEntity _)))
val qName = e.qualifiedName
var name = e.name
Expand Down
45 changes: 26 additions & 19 deletions src/main/scala/com/novocode/extradoc/json/JsonMultiFactory.scala
Expand Up @@ -13,6 +13,8 @@ class JsonMultiFactory(val universe: Universe) extends AbstractJsonFactory {
// the size of extra objects which are included in many pages
override val doInline = false

override val typeEntitiesAsHtml = true

case class Page(no: Int, main: Int) {
val objects = new mutable.HashSet[Int]
val renumbered = new mutable.ArrayBuffer[Int]
Expand All @@ -22,37 +24,42 @@ class JsonMultiFactory(val universe: Universe) extends AbstractJsonFactory {
val (allModels, _) = prepareModel(universe)
val pages = findGlobal(allModels).toSeq.sorted.
zipWithIndex map { case (ord,idx) => (ord, Page(idx, ord))} toMap;
def findPage(j: JBase): Option[Page] = j match {
case j: JObject => j("inTemplate") match {
case Some(Link(target)) =>
pages get target orElse (allModels get target flatMap (findPage _))
case Some(j: JObject) => findPage(j)
case None => None
}
def findPage(ord: Int, j: JBase): Option[Page] = j match {
case j: JObject =>
// Don't map external packages to their parents
if(ord >= 0 && j("isPackage").getOrElse(false) == true && !(pages contains ord)) None
else j("inTemplate") match {
case Some(Link(target)) =>
pages get target orElse (allModels get target flatMap (ch => findPage(target, ch)))
case Some(j: JObject) => findPage(-1, j)
case None => None
}
case _ => None
}
var extra = new mutable.HashSet[Int]
allModels foreach { case (ord, j) =>
(findPage(j) map (_.objects) getOrElse extra) += ord
(pages get ord orElse findPage(ord, j) map (_.objects) getOrElse extra) += ord
}
println("Mapping "+extra.size+" extra objects to all pages that need them")
var extraTotal = 0
pages.values foreach { p =>
p.objects map allModels foreach {
_ foreachRec {
_.links foreach { l =>
if(extra contains l.target) {
if(!(p.objects contains l.target)) {
extraTotal += 1
p.objects += l.target
}
def mapExtras(p: Page, j: JBase) {
j foreachRec {
_.links foreach { l =>
if(extra contains l.target) {
if(!(p.objects contains l.target)) {
extraTotal += 1
p.objects += l.target
mapExtras(p, allModels(l.target))
}
}
}
}
}
pages.values foreach { p =>
p.objects map allModels foreach { j => mapExtras(p, j) }
}
println("Total number of extra objects on all pages: "+extraTotal)
println("Inlining extras on all pages")
println("Inlining objects on all pages")
val keepHtmlLinks = new mutable.HashSet[Int]
allModels.values foreach {
_ foreachRec {
Expand Down Expand Up @@ -95,7 +102,7 @@ class JsonMultiFactory(val universe: Universe) extends AbstractJsonFactory {
for(p <- pages.values) {
p.renumbered += p.main
remappedIDs += Link(p.main) -> (p.no, 0)
p.objects foreach { ord =>
for(ord <- p.objects if ord != p.main) {
remappedIDs += Link(ord) -> (p.no, p.renumbered.size)
p.renumbered += ord
}
Expand Down

0 comments on commit f9759a3

Please sign in to comment.