Merge pull request dart-lang/markdown#55 from srawlins/extension-sets

Extension Sets
diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md
index faafc1d..48c4542 100644
--- a/pkgs/markdown/CHANGELOG.md
+++ b/pkgs/markdown/CHANGELOG.md
@@ -1,9 +1,11 @@
 ## 0.9.0
 
 * Formalize an API for Markdown extensions (#43).
-* **Breaking:** Fenced code blocks are now considered an extension, as
-  they are not part of Markdown.pl.
-* Inline HTML syntax supported. This is also considered an extension (#18).
+* Introduce ExtensionSets. FencedCodeBlock is considered an extension, but
+  existing usage of `markdownToHtml()` and `new Document()` will use the
+  default extension set, which is `ExtensionSet.commonMark`, which includes
+  FencedCodeBlock.
+* Inline HTML syntax support; This is also considered an extension (#18).
 * The text `[foo] (bar)` now parses as an inline link (#53).
 * The text `[foo]()` now renders as an inline link.
 
diff --git a/pkgs/markdown/README.md b/pkgs/markdown/README.md
index 0cbd748..940c5ef 100644
--- a/pkgs/markdown/README.md
+++ b/pkgs/markdown/README.md
@@ -16,9 +16,11 @@
 Syntax extensions
 -----------------
 
-A few Markdown extensions are supported. They are all disabled by default, and
-can be enabled by specifying an Array of extension syntaxes in the `blockSyntaxes` or `inlineSyntaxes`
-argument of `markdownToHtml`.
+A few Markdown extensions, beyond what was specified in the original
+[Perl Markdown][] implementation, are supported. By default, the ones supported
+in [CommonMark] are enabled. Any individual extension can be enabled by
+specifying an Array of extension syntaxes in the `blockSyntaxes` or
+`inlineSyntaxes` argument of `markdownToHtml`.
 
 The currently supported inline extension syntaxes are:
 
@@ -42,6 +44,21 @@
 }
 ```
 
+### Extension Sets
+
+To make extension management easy, you can also just specify an extension set.
+Both `markdownToHtml()` and `new Document()` accept an `extensionSet` named
+parameter. Right now there are two extension sets:
+
+* `ExtensionSet.none` includes no extensions. With no extensions, Markdown
+  documents will be parsed closely to how they might be parsed by the original
+  [Perl Markdown][] implementation.
+* `ExtensionSet.commonMark` includes two extensions so far, which bring this
+  package's Markdown parsing closer to what is found in the [CommonMark] spec:
+
+  * `new InlineHtmlSyntax()`
+  * `const FencedCodeBlockSyntax()`
+
 ### Custom syntax extensions
 
 You can create and use your own syntaxes.
@@ -55,3 +72,6 @@
   //=> <p>~=[,,_,,]:3</p>
 }
 ```
+
+[Perl Markdown]: http://daringfireball.net/projects/markdown/
+[CommonMark]: http://commonmark.org/
diff --git a/pkgs/markdown/lib/markdown.dart b/pkgs/markdown/lib/markdown.dart
index f127450..78e5e7c 100644
--- a/pkgs/markdown/lib/markdown.dart
+++ b/pkgs/markdown/lib/markdown.dart
@@ -8,5 +8,6 @@
 export 'src/ast.dart';
 export 'src/block_parser.dart';
 export 'src/document.dart';
+export 'src/extension_set.dart';
 export 'src/html_renderer.dart';
 export 'src/inline_parser.dart';
diff --git a/pkgs/markdown/lib/src/document.dart b/pkgs/markdown/lib/src/document.dart
index 1190b96..e8b470b 100644
--- a/pkgs/markdown/lib/src/document.dart
+++ b/pkgs/markdown/lib/src/document.dart
@@ -2,22 +2,30 @@
 
 import 'ast.dart';
 import 'block_parser.dart';
+import 'extension_set.dart';
 import 'inline_parser.dart';
 
 /// Maintains the context needed to parse a Markdown document.
 class Document {
-  final Map<String, Link> refLinks;
+  final Map<String, Link> refLinks = {};
   List<BlockSyntax> blockSyntaxes;
   List<InlineSyntax> inlineSyntaxes;
+  ExtensionSet extensionSet;
   Resolver linkResolver;
   Resolver imageLinkResolver;
 
   Document(
-      {this.blockSyntaxes: const [],
-      this.inlineSyntaxes: const [],
+      {this.blockSyntaxes,
+      this.inlineSyntaxes,
+      extensionSet,
       this.linkResolver,
-      this.imageLinkResolver})
-      : refLinks = <String, Link>{};
+      this.imageLinkResolver}) {
+    blockSyntaxes ??= [];
+    inlineSyntaxes ??= [];
+    extensionSet ??= ExtensionSet.commonMark;
+    blockSyntaxes.addAll(extensionSet.blockSyntaxes);
+    inlineSyntaxes.addAll(extensionSet.inlineSyntaxes);
+  }
 
   parseRefLinks(List<String> lines) {
     // This is a hideous regex. It matches:
diff --git a/pkgs/markdown/lib/src/extension_set.dart b/pkgs/markdown/lib/src/extension_set.dart
new file mode 100644
index 0000000..0beb1dd
--- /dev/null
+++ b/pkgs/markdown/lib/src/extension_set.dart
@@ -0,0 +1,14 @@
+import 'block_parser.dart';
+import 'inline_parser.dart';
+
+class ExtensionSet {
+  static ExtensionSet none = new ExtensionSet._([], []);
+
+  static ExtensionSet commonMark = new ExtensionSet._(
+      [const FencedCodeBlockSyntax()], [new InlineHtmlSyntax()]);
+
+  final List blockSyntaxes;
+  final List inlineSyntaxes;
+
+  ExtensionSet._(this.blockSyntaxes, this.inlineSyntaxes);
+}
diff --git a/pkgs/markdown/lib/src/html_renderer.dart b/pkgs/markdown/lib/src/html_renderer.dart
index e477721..d1f7147 100644
--- a/pkgs/markdown/lib/src/html_renderer.dart
+++ b/pkgs/markdown/lib/src/html_renderer.dart
@@ -6,20 +6,23 @@
 
 import 'ast.dart';
 import 'document.dart';
+import 'extension_set.dart';
 import 'inline_parser.dart';
 
 /// Converts the given string of markdown to HTML.
 String markdownToHtml(String markdown,
-    {List<BlockSyntax> blockSyntaxes: const [],
-    List<InlineSyntax> inlineSyntaxes: const [],
+    {List<BlockSyntax> blockSyntaxes,
+    List<InlineSyntax> inlineSyntaxes,
+    ExtensionSet extensionSet,
     Resolver linkResolver,
     Resolver imageLinkResolver,
     bool inlineOnly: false}) {
   var document = new Document(
       blockSyntaxes: blockSyntaxes,
       inlineSyntaxes: inlineSyntaxes,
-      imageLinkResolver: imageLinkResolver,
-      linkResolver: linkResolver);
+      extensionSet: extensionSet,
+      linkResolver: linkResolver,
+      imageLinkResolver: imageLinkResolver);
 
   if (inlineOnly) return renderToHtml(document.parseInline(markdown));
 
diff --git a/pkgs/markdown/lib/src/inline_parser.dart b/pkgs/markdown/lib/src/inline_parser.dart
index 67c5e56..5a496c0 100644
--- a/pkgs/markdown/lib/src/inline_parser.dart
+++ b/pkgs/markdown/lib/src/inline_parser.dart
@@ -209,7 +209,7 @@
 /// TODO(srawlins): improve accuracy while ensuring performance, once
 /// Markdown benchmarking is more mature.
 class InlineHtmlSyntax extends TextSyntax {
-  InlineHtmlSyntax() : super(r'</?[A-Za-z][^>]*>');
+  InlineHtmlSyntax() : super(r'<[/!?]?[A-Za-z][A-Za-z0-9-]*(?: [^>]*)?>');
 }
 
 /// Matches autolinks like `<http://foo.com>`.
diff --git a/pkgs/markdown/pubspec.yaml b/pkgs/markdown/pubspec.yaml
index 9525f32..8af04cf 100644
--- a/pkgs/markdown/pubspec.yaml
+++ b/pkgs/markdown/pubspec.yaml
@@ -4,7 +4,7 @@
 description: A library for converting markdown to HTML.
 homepage: https://github.com/dart-lang/markdown
 environment:
-  sdk: '>=1.8.0 <2.0.0'
+  sdk: '>=1.12.0 <2.0.0'
 dev_dependencies:
   path: '^1.3.1'
   test: '^0.12.4+1'
diff --git a/pkgs/markdown/test/markdown_test.dart b/pkgs/markdown/test/markdown_test.dart
index 8162f0d..4bfee80 100644
--- a/pkgs/markdown/test/markdown_test.dart
+++ b/pkgs/markdown/test/markdown_test.dart
@@ -96,7 +96,7 @@
         1. This will not be an <ol>.
         ''',
         '''
-        1. This will not be an &lt;ol>.
+        1. This will not be an <ol>.
         ''', inlineOnly: true);
   });
 
diff --git a/pkgs/markdown/test/util.dart b/pkgs/markdown/test/util.dart
index 22d1935..e9bd5a8 100644
--- a/pkgs/markdown/test/util.dart
+++ b/pkgs/markdown/test/util.dart
@@ -32,8 +32,8 @@
       .path);
 
 void testFile(String file,
-    {List<BlockSyntax> blockSyntaxes: const [],
-    List<InlineSyntax> inlineSyntaxes: const []}) =>
+    {List<BlockSyntax> blockSyntaxes,
+    List<InlineSyntax> inlineSyntaxes}) =>
   testUnitFile(
       file,
       new File(p.join(_testDir, file)),
@@ -43,8 +43,8 @@
 void testUnitFile(
     String directory,
     File entry,
-    {List<BlockSyntax> blockSyntaxes: const [],
-    List<InlineSyntax> inlineSyntaxes: const []}) {
+    {List<BlockSyntax> blockSyntaxes,
+    List<InlineSyntax> inlineSyntaxes}) {
   group('$directory ${p.basename(entry.path)}', () {
     var lines = entry.readAsLinesSync();
 
@@ -91,8 +91,8 @@
     String description,
     String markdown,
     String html,
-    {List<BlockSyntax> blockSyntaxes: const [],
-    List<InlineSyntax> inlineSyntaxes: const [],
+    {List<BlockSyntax> blockSyntaxes,
+    List<InlineSyntax> inlineSyntaxes,
     Resolver linkResolver,
     Resolver imageLinkResolver,
     bool inlineOnly: false}) {