Skip to content

Commit

Permalink
Merge pull request #22 from jonas/21-support-multiple-snip-sections
Browse files Browse the repository at this point in the history
Aggregate from multiple snip sections
  • Loading branch information
eed3si9n authored Sep 13, 2016
2 parents 23839d0 + 4056a7c commit 8388b80
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import org.pegdown.ast.DirectiveNode.Format._
import org.pegdown.plugins.ToHtmlSerializerPlugin
import org.pegdown.Printer

import scala.collection.JavaConverters._

/**
* Serialize directives, checking the name and format against registered directives.
*/
Expand Down Expand Up @@ -113,9 +115,9 @@ object RefDirective {
case class SnipDirective(page: Page) extends LeafBlockDirective("snip") {
def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = {
try {
val label = Option(node.attributes.identifier)
val labels = node.attributes.values("identifier").asScala
val file = new File(page.file.getParentFile, node.source)
val text = Snippet(file, label)
val text = Snippet(file, labels)
val lang = Option(node.attributes.value("type")).getOrElse(Snippet.language(file))
new VerbatimNode(text, lang).accept(visitor)
} catch {
Expand All @@ -142,7 +144,7 @@ object SnipDirective {
case class FiddleDirective(page: Page) extends LeafBlockDirective("fiddle") {
def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = {
try {
val label = Option(node.attributes.identifier)
val labels = node.attributes.values("identifier").asScala

val baseUrl = node.attributes.value("baseUrl", "https://embed.scalafiddle.io/embed")
val cssClass = node.attributes.value("cssClass", "fiddle")
Expand All @@ -152,7 +154,7 @@ case class FiddleDirective(page: Page) extends LeafBlockDirective("fiddle") {
val cssStyle = node.attributes.value("cssStyle", "overflow: hidden;")

val file = new File(page.file.getParentFile, node.source)
val text = Snippet(file, label)
val text = Snippet(file, labels)
val lang = Option(node.attributes.value("type")).getOrElse(Snippet.language(file))

val fiddleSource = java.net.URLEncoder.encode(
Expand Down
15 changes: 8 additions & 7 deletions core/src/main/scala/com/lightbend/paradox/markdown/Snippet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,18 @@ object Snippet {

class SnippetException(message: String) extends RuntimeException(message)

def apply(file: File, label: Option[String]): String = label match {
case Some(label) => extract(file, label)
case None => extract(file, _ => true, _ => false, addFilteredLine).snippetLines.mkString("\n")
def apply(file: File, labels: Seq[String]): String = labels match {
case Seq() => extract(file, _ => true, _ => false, addFilteredLine).snippetLines.mkString("\n")
case _ => labels.map(label => extract(file, label)).mkString("\n")
}

def extract(file: File, label: String): String = {
if (!verifyLabel(label)) throw new SnippetException(s"Label [$label] for [$file] contains illegal characters. " +
"Only [a-zA-Z0-9_-] are allowed.")
// A label can be followed by an end of line or a space followed by a single sequence of contiguous
// (no whitespace) non-word characters (anything not in the group [a-zA-Z0-9_]
val labelPattern = ("""#\Q""" + label + """\E( [^w \t]*)?$""").r
// A label can be followed by an end of line or one or more spaces followed by an
// optional single sequence of contiguous (no whitespace) non-word characters
// (anything not in the group [a-zA-Z0-9_])
val labelPattern = ("""#\Q""" + label + """\E( +[^w \t]*)?$""").r
val hasLabel = (s: String) => labelPattern.findFirstIn(s).nonEmpty
val extractionState = extract(file, hasLabel, hasLabel, addFilteredLine)
val snippetLines = extractionState.snippetLines
Expand All @@ -59,7 +60,7 @@ object Snippet {

private case class ExtractionState(inBlock: Boolean, snippetLines: Seq[String])

private val anyLabelRegex = """#[a-zA-Z_0-9\-]+( [^w \t]*)?$""".r
private val anyLabelRegex = """#[a-zA-Z_0-9\-]+( +[^w \t]*)?$""".r
private def addFilteredLine(line: String, lines: Seq[String]): Seq[String] =
anyLabelRegex.findFirstIn(line).map(_ => lines).getOrElse(lines :+ line)
private def verifyLabel(label: String): Boolean = anyLabelRegex.findFirstIn(s"#$label").nonEmpty
Expand Down
15 changes: 15 additions & 0 deletions plugin/src/sbt-test/paradox/snippets/expected/multiple.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
<pre class="prettyprint"><code class="language-scala">import scala.concurrent.duration._

case class Measurement(method: Method, duration: Duration)</code></pre>
<pre class="prettyprint"><code class="language-scala">import scala.util.Try

def parseInt(s: String): Option[Int] = Try(s.toInt).toOption</code></pre>
<pre class="prettyprint"><code class="language-conf"># HTTP Configuration
http {
port=80
host=0.0.0.0
}

# Database Configuration
db {
url=jdbc:mysql://mydb/mytable
user=dev
pass=secret
}</code></pre>
2 changes: 2 additions & 0 deletions plugin/src/sbt-test/paradox/snippets/expected/snippets.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
<pre class="prettyprint"><code class="language-conf">snippets {
test = 1
}</code></pre>
<pre class="prettyprint"><code class="language-scala">val symbols = Seq(&#39;symbols, Symbol(&quot;@&quot;), &#39;EOL)</code></pre>
<pre class="prettyprint"><code class="language-scala">val spacy = &quot;Please do not remove ending spaces after these markers&quot;</code></pre>
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
@@ snip [multiple snippet](../../test/scala/Multiple.scala) { #multiple }

@@ snip [multi-label snippet](../../test/scala/Multiple.scala) { #parseint-imports #parseint-def }

@@ snip [multi-label conf snippet](../../test/scala/Multiple.scala) { #http-config #db-config type=conf }
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@@ snip [indented snippet](../../test/scala/Snippets.scala) { #indented }

@@ snip [typed snippet](../../test/scala/Snippets.scala) { #config type=conf }

@@ snip [symbols @ EOL snippet](../../test/scala/Snippets.scala) { identifier=symbols-at-eol }

@@ snip [lenient space snippet](../../test/scala/Snippets.scala) { #space-after-marker }
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// #parseint-imports
import scala.util.Try
// #parseint-imports

object Multiple {
// #multiple
import scala.concurrent.duration._
Expand All @@ -14,4 +18,30 @@ object Multiple {
// #multiple
case class Measurement(method: Method, duration: Duration)
// #multiple
}

// #parseint-def

def parseInt(s: String): Option[Int] = Try(s.toInt).toOption
// #parseint-def

val config = """
#http-config
# HTTP Configuration
http {
port=80
host=0.0.0.0
}
#http-config
http.port=${?HTTP_PORT}
#db-config
# Database Configuration
db {
url=jdbc:mysql://mydb/mytable
user=dev
pass=secret
}
#db-config
"""
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ object Snippets {
}
// #indented

//#symbols-at-eol ¯\_(ツ)_/¯
val symbols = Seq('symbols, Symbol("@"), 'EOL)
//#symbols-at-eol ¯\_(ツ)_/¯

//#space-after-marker
val spacy = "Please do not remove ending spaces after these markers"
//#space-after-marker

val config = """
#config
snippets {
Expand Down

0 comments on commit 8388b80

Please sign in to comment.