package dotty.tools package dottydoc package model package comment import dotc.core.Contexts.Context import dotc.util.Positions._ import dotty.tools.dottydoc.util.syntax._ import util.MemberLookup import com.vladsch.flexmark.ast.{ Node => MarkdownNode } import com.vladsch.flexmark.html.HtmlRenderer import com.vladsch.flexmark.parser.Parser import com.vladsch.flexmark.util.sequence.CharSubSequence object HtmlParsers { implicit class StringToMarkdown(val text: String) extends AnyVal { def toMarkdown(origin: Entity)(implicit ctx: Context): MarkdownNode = { import com.vladsch.flexmark.ast.{ Link, Visitor, VisitHandler, NodeVisitor } val inlineToHtml = InlineToHtml(origin) val node = Parser.builder(staticsite.Site.markdownOptions) .build.parse(text) def isOuter(url: String) = url.startsWith("http://") || url.startsWith("https://") || url.startsWith("ftp://") || url.startsWith("ftps://") def isRelative(url: String) = url.startsWith("../") || url.startsWith("./") val linkVisitor = new NodeVisitor( new VisitHandler(classOf[Link], new Visitor[Link] with MemberLookup { def queryToUrl(title: String, link: String) = makeEntityLink(origin, ctx.docbase.packages, Text(title), link).link match { case Tooltip(_) => "#" case LinkToExternal(_, url) => url case LinkToEntity(t: Entity) => t match { case e: Entity with Members => inlineToHtml.relativePath(t) case x => x.parent.fold("#") { xpar => inlineToHtml.relativePath(xpar) } } } override def visit(link: Link) = { val linkUrl = link.getUrl.toString if (!isOuter(linkUrl) && !isRelative(linkUrl)) link.setUrl(CharSubSequence.of(queryToUrl(link.getTitle.toString, linkUrl))) } }) ) linkVisitor.visit(node) node } def toMarkdownString(origin: Entity)(implicit ctx: Context): String = toMarkdown(origin).show } implicit class MarkdownToHtml(val markdown: MarkdownNode) extends AnyVal { def show(implicit ctx: Context): String = HtmlRenderer.builder(staticsite.Site.markdownOptions).build().render(markdown) def shortenAndShow(implicit ctx: Context): String = (new MarkdownShortener).shorten(markdown).show } implicit class StringToWiki(val text: String) extends AnyVal { def toWiki(origin: Entity, packages: Map[String, Package], pos: Position): Body = new WikiParser(origin, packages, text, pos, origin.symbol).document() } implicit class BodyToHtml(val body: Body) extends AnyVal { def show(origin: Entity): String = { val inlineToHtml = InlineToHtml(origin) def bodyToHtml(body: Body): String = (body.blocks map blockToHtml).mkString def blockToHtml(block: Block): String = block match { case Title(in, 1) => s"
${inlineToHtml(in)}
" case Code(data) => s"""$data
"""
case UnorderedList(items) =>
s"${toHtml(in)}
"
case Text(text) => text
case Summary(in) => toHtml(in)
case HtmlTag(tag) => tag
case EntityLink(target, link) => enityLinkToHtml(target, link)
}
def enityLinkToHtml(target: Inline, link: LinkTo) = link match {
case Tooltip(_) => toHtml(target)
case LinkToExternal(n, url) => s"""$n"""
case LinkToEntity(t: Entity) => t match {
// Entity is a package member
case e: Entity with Members =>
s"""${toHtml(target)}"""
// Entity is a Val / Def
case x => x.parent.fold(toHtml(target)) { xpar =>
s"""${toHtml(target)}"""
}
}
}
}
}