diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2017-01-05 13:52:58 +0100 |
---|---|---|
committer | Felix Mulder <felix.mulder@gmail.com> | 2017-01-31 14:29:17 +0100 |
commit | 56cec80db7ab46c69cbbc8551ddf3c9857f8a804 (patch) | |
tree | bdb1f423438732bb71c9b15afefe09f34dd94f17 /doc-tool/src/dotty | |
parent | 08dce0704570ae8346fc28019ef5264f1e12ce25 (diff) | |
download | dotty-56cec80db7ab46c69cbbc8551ddf3c9857f8a804.tar.gz dotty-56cec80db7ab46c69cbbc8551ddf3c9857f8a804.tar.bz2 dotty-56cec80db7ab46c69cbbc8551ddf3c9857f8a804.zip |
Implement shortening of Markdown AST for summaries
Diffstat (limited to 'doc-tool/src/dotty')
4 files changed, 100 insertions, 34 deletions
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala index f2122572b..963c72bc9 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala @@ -25,7 +25,6 @@ class ContextDottydoc extends ContextDocstrings { s -> _defs.get(s).map(xs => xs + d).getOrElse(Set(d)) }) - val markdownOptions: DataHolder = new MutableDataSet() .setFrom(ParserEmulationFamily.KRAMDOWN.getOptions) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala index 8d927cb28..842746338 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala @@ -68,28 +68,27 @@ object MarkdownComment extends util.MemberLookup { } } - val parsedBody = parsed.body.fromMarkdown(ent) Comment( - body = parsedBody, - short = parsedBody, - authors = filterEmpty(parsed.authors).map(_.fromMarkdown(ent)), - see = filterEmpty(parsed.see).map(_.fromMarkdown(ent)), - result = single("@result", parsed.result).map(_.fromMarkdown(ent)), - throws = linkedExceptions(parsed.throws).mapValues(_.fromMarkdown(ent)), - valueParams = filterEmpty(parsed.valueParams).mapValues(_.fromMarkdown(ent)), - typeParams = filterEmpty(parsed.typeParams).mapValues(_.fromMarkdown(ent)), - version = single("@version", parsed.version).map(_.fromMarkdown(ent)), - since = single("@since", parsed.since).map(_.fromMarkdown(ent)), - todo = filterEmpty(parsed.todo).map(_.fromMarkdown(ent)), - deprecated = single("@deprecated", parsed.deprecated, filter = false).map(_.fromMarkdown(ent)), - note = filterEmpty(parsed.note).map(_.fromMarkdown(ent)), - example = filterEmpty(parsed.example).map(_.fromMarkdown(ent)), - constructor = single("@constructor", parsed.constructor).map(_.fromMarkdown(ent)), - group = single("@group", parsed.group).map(_.fromMarkdown(ent)), - groupDesc = filterEmpty(parsed.groupDesc).mapValues(_.fromMarkdown(ent)), - groupNames = filterEmpty(parsed.groupNames).mapValues(_.fromMarkdown(ent)), - groupPrio = filterEmpty(parsed.groupPrio).mapValues(_.fromMarkdown(ent)), - hideImplicitConversions = filterEmpty(parsed.hideImplicitConversions).map(_.fromMarkdown(ent)) + body = parsed.body.toMarkdownString(ent), + short = parsed.body.toMarkdown(ent).shortenAndShow, + authors = filterEmpty(parsed.authors).map(_.toMarkdownString(ent)), + see = filterEmpty(parsed.see).map(_.toMarkdownString(ent)), + result = single("@result", parsed.result).map(_.toMarkdownString(ent)), + throws = linkedExceptions(parsed.throws).mapValues(_.toMarkdownString(ent)), + valueParams = filterEmpty(parsed.valueParams).mapValues(_.toMarkdownString(ent)), + typeParams = filterEmpty(parsed.typeParams).mapValues(_.toMarkdownString(ent)), + version = single("@version", parsed.version).map(_.toMarkdownString(ent)), + since = single("@since", parsed.since).map(_.toMarkdownString(ent)), + todo = filterEmpty(parsed.todo).map(_.toMarkdownString(ent)), + deprecated = single("@deprecated", parsed.deprecated, filter = false).map(_.toMarkdownString(ent)), + note = filterEmpty(parsed.note).map(_.toMarkdownString(ent)), + example = filterEmpty(parsed.example).map(_.toMarkdownString(ent)), + constructor = single("@constructor", parsed.constructor).map(_.toMarkdownString(ent)), + group = single("@group", parsed.group).map(_.toMarkdownString(ent)), + groupDesc = filterEmpty(parsed.groupDesc).mapValues(_.toMarkdownString(ent)), + groupNames = filterEmpty(parsed.groupNames).mapValues(_.toMarkdownString(ent)), + groupPrio = filterEmpty(parsed.groupPrio).mapValues(_.toMarkdownString(ent)), + hideImplicitConversions = filterEmpty(parsed.hideImplicitConversions).map(_.toMarkdownString(ent)) ) } @@ -114,7 +113,7 @@ object WikiComment extends util.MemberLookup { def apply(parsed: ParsedComment, ent: Entity, pos: Position)(implicit ctx: Context): Comment = { val inlineToHtml = InlineToHtml(ent) val packages = ctx.docbase.packages - val parsedBody = parsed.body.toWiki(ent, packages, pos).wikiToString(ent) + val parsedBody = parsed.body.toWiki(ent, packages, pos).show(ent) def linkedExceptions(m: Map[String, Body]): Map[String, Body] = { m.map { case (targetStr, body) => @@ -131,7 +130,7 @@ object WikiComment extends util.MemberLookup { } def toWiki(str: String): Body = str.toWiki(ent, packages, pos) - def toString(body: Body): String = body.wikiToString(ent) + def toString(body: Body): String = body.show(ent) def filterEmpty(xs: List[String]): List[Body] = xs.map(toWiki).filterNot(_.blocks.isEmpty) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala index 24572925c..d3b695aac 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala @@ -8,22 +8,22 @@ 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 MarkdownToHtml(val text: String) extends AnyVal { - def fromMarkdown(origin: Entity)(implicit ctx: Context): String = { - import com.vladsch.flexmark.util.sequence.CharSubSequence + 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 } - import com.vladsch.flexmark.parser.Parser - import com.vladsch.flexmark.html.HtmlRenderer val inlineToHtml = InlineToHtml(origin) - // TODO: split out into different step so that we can get a short summary val node = Parser.builder(ctx.docbase.markdownOptions) .build.parse(text) - implicit def toCharSeq(str: String) = CharSubSequence.of(str) def isOuter(url: String) = url.startsWith("http://") || @@ -49,14 +49,25 @@ object HtmlParsers { override def visit(link: Link) = { val linkUrl = link.getUrl.toString if (!isOuter(linkUrl) && !isRelative(linkUrl)) - link.setUrl(queryToUrl(linkUrl)) + link.setUrl(CharSubSequence.of(queryToUrl(linkUrl))) } }) ) linkVisitor.visit(node) - HtmlRenderer.builder(ctx.docbase.markdownOptions).build().render(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(ctx.docbase.markdownOptions).build().render(markdown) + + def shortenAndShow(implicit ctx: Context): String = + (new MarkdownShortener).shorten(markdown).show } implicit class StringToWiki(val text: String) extends AnyVal { @@ -65,7 +76,7 @@ object HtmlParsers { } implicit class BodyToHtml(val body: Body) extends AnyVal { - def wikiToString(origin: Entity): String = { + def show(origin: Entity): String = { val inlineToHtml = InlineToHtml(origin) def bodyToHtml(body: Body): String = diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala new file mode 100644 index 000000000..841232e52 --- /dev/null +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala @@ -0,0 +1,57 @@ +package dotty.tools +package dottydoc +package model +package comment + +/** The `MarkdownShortener` takes a node and *mutates* it and all children so + * that the displayed length of the generated HTML doesn't exceeed `maxLen`. + * This number defaults to 150 characters. + * + * @note calling `shorten` **will** mutate the Markdown AST node. + */ +class MarkdownShortener { + import com.vladsch.flexmark.ast._ + + def shorten(node: Node, maxLen: Int = 150): Node = { + var len = 0 + + def count(node: Node, length: => Int, shortenOrUnlink: Int => Unit) = { + val remaining = math.max(maxLen - len, 0) + if (remaining == 0) node.unlink() + else { + if (length <= remaining) len += length + else { + shortenOrUnlink(remaining) + len = maxLen + } + } + } + + val nodeVisitor = new NodeVisitor( + new VisitHandler(classOf[Text], new Visitor[Text] { + override def visit(node: Text) = count( + node, + node.getChars.length, + remaining => node.setChars( + node.getChars.subSequence(0, remaining).trimEnd.append("...") + ) + ) + }), + new VisitHandler(classOf[Code], new Visitor[Code] { + override def visit(node: Code) = count( + node, + node.getText.length, + remaining => node.setText( + node.getText.subSequence(0, remaining).trimEnd.append("...") + ) + ) + }), + new VisitHandler(classOf[Image], new Visitor[Image] { + override def visit(node: Image) = count(node, maxLen, _ => node.unlink()) + }) + ) + + nodeVisitor.visit(node) + node + } +} |