dotty.tools.dottydoc.staticsite.Template.scala Maven / Gradle / Ivy
The newest version!
package dotty.tools
package dottydoc
package staticsite
import scala.util.control.NonFatal
import dotc.util.SourceFile
import dotc.core.Contexts.Context
import dotc.util.Spans.Span
import util.syntax._
trait Template {
def path: String
def content: SourceFile
def show: String = new String(content.content)
}
case class TemplateRenderingError(path: String, ex: Throwable)
extends Exception(s"error rendering $path, $ex")
case class Layout(path: String, content: SourceFile) extends Template
case class Include(path: String, content: SourceFile) extends Template
case class LiquidTemplate(path: String, content: SourceFile) extends Template with ResourceFinder {
import scala.collection.JavaConverters._
import dotc.printing.Highlighting._
import liqp.Template
import liqp.filters.Filter
import liqp.parser.Flavor.JEKYLL
import java.util.{ HashMap, Map => JMap }
import filters._
import tags._
/** Register filters to static container */
Filter.registerFilter(new Reverse)
Filter.registerFilter(new First)
Filter.registerFilter(new Json)
// For some reason, liqp rejects a straight conversion using `.asJava`
private def toJavaMap(map: Map[String, AnyRef]): HashMap[String, Object] =
map.foldLeft(new HashMap[String, Object]()) { case (map, (k, v)) =>
map.put(k, v)
map
}
private def protectedRender(op: => String)(implicit ctx: Context) = try {
Some(op)
} catch {
case NonFatal(ex) => {
// TODO: when we reimplement the liquid parser, this can go away. For now
// this is an OK approximation of what went wrong.
if ((ex.getCause eq null) || ex.getMessage.contains("exceeded the max amount of time")) {
ctx.docbase.error(
"unknown error occurred in " +
Blue(path).toString +
", most likely incorrect usage of tag"
)
None
}
else ex.getCause match {
case mm: org.antlr.runtime.MismatchedTokenException => {
val unexpected = LiquidTemplate.token(mm.getUnexpectedType)
val expected = LiquidTemplate.token(mm.expecting)
ctx.error(
if (unexpected == "EOF")
s"unexpected end of file, expected: '$expected'"
else
s"unexpected token '$unexpected', expected: '$expected'",
content atSpan Span(mm.index)
)
None
}
case ex => {
if (true || ctx.settings.Ydebug.value)
throw ex
None
}
}
}
}
def render(params: Map[String, AnyRef], includes: Map[String, Include])(implicit ctx: Context): Option[String] =
protectedRender {
Template.parse(show, JEKYLL)
.`with`(ResourceInclude(params, includes))
.`with`(RenderReference(params))
.`with`(RenderLink(params))
.`with`(RenderTitle(params))
.`with`(Docstring(params))
.render(toJavaMap(params))
}
}
object LiquidTemplate {
import liqp.parser.LiquidParser
private val _tokens: Map[String, String] = Map(
"TagStart" -> "{%",
"TagEnd" -> "%}"
)
def token(i: Int): String =
if (i == -1) "EOF"
else if (i >= LiquidParser.tokenNames.length)
"non-existing token"
else _tokens
.get(LiquidParser.tokenNames(i))
.getOrElse(s"token $i")
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy