Merge pull request dart-lang/markdown#6 from dikmax/pandoc-code-blocks

Pandoc-style code blocks
diff --git a/pkgs/markdown/lib/src/markdown/block_parser.dart b/pkgs/markdown/lib/src/markdown/block_parser.dart
index 42b9353..d163e9c 100644
--- a/pkgs/markdown/lib/src/markdown/block_parser.dart
+++ b/pkgs/markdown/lib/src/markdown/block_parser.dart
@@ -19,8 +19,8 @@
 /// A line indented four spaces. Used for code blocks and lists.
 final _RE_INDENT = new RegExp(r'^(?:    |\t)(.*)$');
 
-/// GitHub style triple quoted code block.
-final _RE_CODE = new RegExp(r'^```(.*)$');
+/// Fenced code block.
+final _RE_CODE = new RegExp(r'^(`{3,}|~{3,})(.*)$');
 
 /// Three or more hyphens, asterisks or underscores by themselves. Note that
 /// a line like `----` is valid as both HR and SETEXT. In case of a tie,
@@ -97,7 +97,7 @@
           new SetextHeaderSyntax(),
           new HeaderSyntax(),
           new CodeBlockSyntax(),
-          new GitHubCodeBlockSyntax(),
+          new FencedCodeBlockSyntax(),
           new BlockquoteSyntax(),
           new HorizontalRuleSyntax(),
           new UnorderedListSyntax(),
@@ -244,16 +244,17 @@
   }
 }
 
-/// Parses preformatted code blocks between two ``` sequences.
-class GitHubCodeBlockSyntax extends BlockSyntax {
+/// Parses preformatted code blocks between two ~~~ or ``` sequences.
+/// [Pandoc's markdown documentation](http://johnmacfarlane.net/pandoc/demo/example9/pandocs-markdown.html).
+class FencedCodeBlockSyntax extends BlockSyntax {
   RegExp get pattern => _RE_CODE;
 
-  List<String> parseChildLines(BlockParser parser) {
+  List<String> parseChildLines(BlockParser parser, String endBlock) {
     final childLines = <String>[];
     parser.advance();
     while (!parser.isDone) {
       var match = pattern.firstMatch(parser.current);
-      if (match == null) {
+      if (match == null || !match[1].startsWith(endBlock)) {
         childLines.add(parser.current);
         parser.advance();
       } else {
@@ -266,9 +267,11 @@
 
   Node parse(BlockParser parser) {
     // Get the syntax identifier, if there is one.
-    var syntax = pattern.firstMatch(parser.current).group(1);
-    
-    final childLines = parseChildLines(parser);
+    var match = pattern.firstMatch(parser.current);
+    var endBlock = match.group(1);
+    var syntax = match.group(2);
+
+    final childLines = parseChildLines(parser, endBlock);
 
     // The Markdown tests expect a trailing newline.
     childLines.add('');
@@ -276,7 +279,15 @@
     // Escape the code.
     final escaped = escapeHtml(childLines.join('\n'));
 
-    return new Element('pre', [new Element.text('code', escaped)]);
+    var element = new Element('pre', [new Element.text('code', escaped)]);
+    if (syntax != '') {
+      element.attributes['class'] = syntax;
+    }
+    return element;
+  }
+
+  void _addElementAttributes(Element element) {
+
   }
 }
 
diff --git a/pkgs/markdown/test/markdown_test.dart b/pkgs/markdown/test/markdown_test.dart
index 63ffb91..1e4b0c9 100644
--- a/pkgs/markdown/test/markdown_test.dart
+++ b/pkgs/markdown/test/markdown_test.dart
@@ -439,7 +439,7 @@
         code
         ```
         ''', '''
-        <pre><code>code
+        <pre class="dart"><code>code
         </code></pre>
         ''');
 
@@ -451,6 +451,37 @@
         <pre><code>&lt;&amp;&gt;
         </code></pre>
         ''');
+
+    validate('Pandoc style without language identifier', '''
+        ~~~~~
+        code
+        ~~~~~
+        ''', '''
+        <pre><code>code
+        </code></pre>
+        ''');
+
+    validate('Pandoc style with language identifier', '''
+        ~~~~~dart
+        code
+        ~~~~~
+        ''', '''
+        <pre class="dart"><code>code
+        </code></pre>
+        ''');
+
+    validate('Pandoc style with inner tildes row', '''
+        ~~~~~
+        ~~~
+        code
+        ~~~
+        ~~~~~
+        ''', '''
+        <pre><code>~~~
+        code
+        ~~~
+        </code></pre>
+        ''');
   });
 
   group('Horizontal rules', () {