From c8a1a80776630535150d041a0aef34c508476cb3 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Fri, 6 Jan 2017 13:54:07 +0100 Subject: Add `Page` trait with concrete classes for HTML and MD --- .../src/dotty/tools/dottydoc/staticsite/Page.scala | 53 +++++++++-- doc-tool/test/StaticPageTests.scala | 106 +++++++++++++++++++++ doc-tool/test/YamlTest.scala | 69 -------------- 3 files changed, 149 insertions(+), 79 deletions(-) create mode 100644 doc-tool/test/StaticPageTests.scala delete mode 100644 doc-tool/test/YamlTest.scala (limited to 'doc-tool') diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala index 7048109fd..33667cf61 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala @@ -4,15 +4,22 @@ package staticsite import dotc.core.Contexts.Context import dotty.tools.dottydoc.util.syntax._ +import dotc.config.Printers.dottydoc import com.vladsch.flexmark.html.HtmlRenderer import com.vladsch.flexmark.parser.Parser import com.vladsch.flexmark.ext.front.matter.AbstractYamlFrontMatterVisitor import liqp.{ Template => LiquidTemplate } -class MarkdownPage(fileContents: => String, params: Map[String, AnyRef]) { +case class IllegalFrontMatter(message: String) extends Exception(message) + +trait Page { import scala.collection.JavaConverters._ + + def pageContent: String + def params: Map[String, AnyRef] + def yaml(implicit ctx: Context): Map[String, String] = { if (_yaml eq null) initFields() _yaml @@ -23,28 +30,54 @@ class MarkdownPage(fileContents: => String, params: Map[String, AnyRef]) { _html } - private[this] var _yaml: Map[String, String] = _ - private[this] var _html: String = _ - private[this] def initFields()(implicit ctx: Context) = { - val template = LiquidTemplate.parse(fileContents) + protected[this] var _yaml: Map[String, String] = _ + protected[this] var _html: String = _ + protected[this] def initFields()(implicit ctx: Context) = { + val md = Parser.builder(ctx.docbase.markdownOptions).build.parse(pageContent) val yamlCollector = new AbstractYamlFrontMatterVisitor() - val mdParser = Parser.builder(ctx.docbase.markdownOptions).build - - yamlCollector.visit(mdParser.parse(fileContents)) + yamlCollector.visit(md) _yaml = yamlCollector .getData().asScala .mapValues(_.asScala.headOption.getOrElse("")) .toMap + // YAML must start with "---" and end in either "---" or "..." + val withoutYaml = + if (pageContent.startsWith("---\n")) { + val str = + pageContent.lines + .drop(1) + .dropWhile(line => line != "---" && line != "...") + .drop(1).mkString("\n") + + if (str.isEmpty) throw IllegalFrontMatter(pageContent) + else str + } + else pageContent + // make accessible via "{{ page.title }}" in templates val page = Map("page" -> _yaml.asJava) - val renderedTemplate = template.render((page ++ params).asJava) + _html = LiquidTemplate + .parse(withoutYaml) + .render((page ++ params).asJava) + } +} + +class HtmlPage(fileContents: => String, val params: Map[String, AnyRef]) extends Page { + lazy val pageContent = fileContents +} + +class MarkdownPage(fileContents: => String, val params: Map[String, AnyRef]) extends Page { + lazy val pageContent = fileContents + override protected[this] def initFields()(implicit ctx: Context) = { + super.initFields() + val md = Parser.builder(ctx.docbase.markdownOptions).build.parse(_html) _html = HtmlRenderer .builder(ctx.docbase.markdownOptions) .escapeHtml(false) .build() - .render(mdParser.parse(renderedTemplate)) + .render(md) } } diff --git a/doc-tool/test/StaticPageTests.scala b/doc-tool/test/StaticPageTests.scala new file mode 100644 index 000000000..1b22665c8 --- /dev/null +++ b/doc-tool/test/StaticPageTests.scala @@ -0,0 +1,106 @@ +package dotty.tools +package dottydoc + +import org.junit.Test +import org.junit.Assert._ + +import staticsite.{ MarkdownPage, HtmlPage, IllegalFrontMatter } + +class StaticPageTests extends DottyDocTest { + import scala.collection.JavaConverters._ + + @Test def mdHas1Key = { + val page = new MarkdownPage( + """|--- + |key: + |--- + | + |great""".stripMargin, + Map.empty + ) + + assert( + page.yaml == Map("key" -> ""), + s"""incorrect yaml, expected "key:" without key in: ${page.yaml}""" + ) + + assertEquals("

great

\n", page.html) + } + + @Test def yamlPreservesLiquidTags = { + val page1 = new MarkdownPage( + """|--- + |key: + |--- + | + |{{ content }}""".stripMargin, + Map("content" -> "Hello, world!") + ) + + assert( + page1.yaml == Map("key" -> ""), + s"""incorrect yaml, expected "key:" without key in: ${page1.yaml}""" + ) + + assertEquals("

Hello, world!

\n", page1.html) + + val page2 = new MarkdownPage( + """|{{ content }}""".stripMargin, + Map("content" -> "hello") + ) + assert( + page2.yaml == Map(), + s"""incorrect yaml, expected "key:" without key in: ${page2.yaml}""" + ) + assertEquals("

hello

\n", page2.html) + + val page3 = new MarkdownPage( + """|{% if product.title == "Awesome Shoes" %} + |These shoes are awesome! + |{% endif %}""".stripMargin, + Map("product" -> Map("title" -> "Awesome Shoes").asJava) + ) + + assertEquals( + "

These shoes are awesome!

\n", + page3.html + ) + } + + @Test def simpleHtmlPage = { + val p1 = new HtmlPage("""

{{ "hello, world!" }}

""", Map.empty) + assert(p1.yaml == Map(), "non-empty yaml found") + assertEquals("

hello, world!

", p1.html) + } + + @Test def htmlPageHasNoYaml = { + val page = new HtmlPage( + """|--- + |layout: main + |--- + | + |Hello, world!""".stripMargin, + Map.empty + ) + + assert(!page.html.contains("---\nlayout: main\n---"), + s"page still contains yaml:\n${page.html}") + } + + @Test def illegalYamlFrontMatter = try { + val page = new HtmlPage( + """|--- + |layout: main + | + | + |Hello, world!""".stripMargin, + Map.empty + ) + + page.html + fail("illegal front matter didn't throw exception") + } catch { + case IllegalFrontMatter(x) => // success! + case t: Throwable => throw t + } +} diff --git a/doc-tool/test/YamlTest.scala b/doc-tool/test/YamlTest.scala deleted file mode 100644 index 2d633d12c..000000000 --- a/doc-tool/test/YamlTest.scala +++ /dev/null @@ -1,69 +0,0 @@ -package dotty.tools -package dottydoc - -import org.junit.Test -import org.junit.Assert._ - -import staticsite.MarkdownPage - -class YamlTest extends DottyDocTest { - import scala.collection.JavaConverters._ - - @Test def has1Key = { - val page = new MarkdownPage( - """|--- - |key: - |--- - | - |great""".stripMargin, - Map.empty - ) - - assert( - page.yaml == Map("key" -> ""), - s"""incorrect yaml, expected "key:" without key in: ${page.yaml}""" - ) - - assertEquals("

great

\n", page.html) - } - - @Test def yamlPreservesLiquidTags = { - val page1 = new MarkdownPage( - """|--- - |key: - |--- - | - |{{ content }}""".stripMargin, - Map("content" -> "Hello, world!") - ) - - assert( - page1.yaml == Map("key" -> ""), - s"""incorrect yaml, expected "key:" without key in: ${page1.yaml}""" - ) - - assertEquals("

Hello, world!

\n", page1.html) - - val page2 = new MarkdownPage( - """|{{ content }}""".stripMargin, - Map("content" -> "hello") - ) - assert( - page2.yaml == Map(), - s"""incorrect yaml, expected "key:" without key in: ${page2.yaml}""" - ) - assertEquals("

hello

\n", page2.html) - - val page3 = new MarkdownPage( - """|{% if product.title == "Awesome Shoes" %} - |These shoes are awesome! - |{% endif %}""".stripMargin, - Map("product" -> Map("title" -> "Awesome Shoes").asJava) - ) - - assertEquals( - "

These shoes are awesome!

\n", - page3.html - ) - } -} -- cgit v1.2.3