Fix image alt text
diff --git a/pkgs/markdown/lib/src/ast.dart b/pkgs/markdown/lib/src/ast.dart
index 5cc3e7c..fa623be 100644
--- a/pkgs/markdown/lib/src/ast.dart
+++ b/pkgs/markdown/lib/src/ast.dart
@@ -11,6 +11,8 @@
 /// Roughly corresponds to Node in the DOM. Will be either an Element or Text.
 abstract class Node {
   void accept(NodeVisitor visitor);
+
+  String get textContent;
 }
 
 /// A named tag that can contain other nodes.
@@ -47,6 +49,10 @@
       visitor.visitElementAfter(this);
     }
   }
+
+  String get textContent => children == null
+      ? ''
+      : children.map((Node child) => child.textContent).join('');
 }
 
 /// A plain text element.
@@ -55,6 +61,8 @@
   Text(this.text);
 
   void accept(NodeVisitor visitor) => visitor.visitText(this);
+
+  String get textContent => text;
 }
 
 /// Visitor pattern for the AST.
diff --git a/pkgs/markdown/lib/src/inline_parser.dart b/pkgs/markdown/lib/src/inline_parser.dart
index d8b8c0d..595b4b5 100644
--- a/pkgs/markdown/lib/src/inline_parser.dart
+++ b/pkgs/markdown/lib/src/inline_parser.dart
@@ -292,7 +292,7 @@
   /// breaks it into pieces.
   static get linkPattern {
     var refLink = r'\[([^\]]*)\]'; // `[id]` reflink id.
-    var title = r'(?:\s*"([^"]+?)"|)'; // Optional title in quotes.
+    var title = r'(?:\s*"([^"]+?)"\s*|)'; // Optional title in quotes.
     var inlineLink = '\\((\\S*?)$title\\)'; // `(url "title")` link.
     return '\](?:($refLink|$inlineLink)|)';
 
@@ -409,14 +409,12 @@
     if (link == null) return null;
     var image = new Element.empty("img");
     image.attributes["src"] = escapeHtml(link.url);
+    image.attributes["alt"] = state?.textContent ?? '';
 
     if (link.title != null) {
       image.attributes["title"] = escapeHtml(link.title);
     }
 
-    var alt = state.children.map((e) => e is Text ? e.text : "").join(" ");
-    if (alt != "") image.attributes["alt"] = alt;
-
     return image;
   }
 }
@@ -536,4 +534,7 @@
 
     return null;
   }
+
+  String get textContent =>
+      children.map((Node child) => child.textContent).join('');
 }
diff --git a/pkgs/markdown/test/original/inline_images.unit b/pkgs/markdown/test/original/inline_images.unit
index 45316b6..9ce0674 100644
--- a/pkgs/markdown/test/original/inline_images.unit
+++ b/pkgs/markdown/test/original/inline_images.unit
@@ -2,7 +2,7 @@
 ![](http://foo.com/foo.png)
 
 <<<
-<p><img src="http://foo.com/foo.png" /></p>
+<p><img alt="" src="http://foo.com/foo.png" /></p>
 >>> alternate text
 ![alternate text](http://foo.com/foo.png)
 
@@ -12,9 +12,9 @@
 ![](http://foo.com/foo.png "optional title")
 
 <<<
-<p><img src="http://foo.com/foo.png" title="optional title" /></p>
+<p><img alt="" src="http://foo.com/foo.png" title="optional title" /></p>
 >>> invalid alt text
 ![`alt`](http://foo.com/foo.png)
 
 <<<
-<p><img src="http://foo.com/foo.png" /></p>
+<p><img alt="alt" src="http://foo.com/foo.png" /></p>
diff --git a/pkgs/markdown/test/original/inline_links.unit b/pkgs/markdown/test/original/inline_links.unit
index 2e33754..dd0a65d 100644
--- a/pkgs/markdown/test/original/inline_links.unit
+++ b/pkgs/markdown/test/original/inline_links.unit
@@ -17,7 +17,7 @@
 links [![](/are.png)](http://foo.com) awesome
 
 <<<
-<p>links <a href="http://foo.com"><img src="/are.png" /></a> awesome</p>
+<p>links <a href="http://foo.com"><img alt="" src="/are.png" /></a> awesome</p>
 >>> image with alt inside link
 links [![my alt](/are.png)](http://foo.com) awesome
 
@@ -27,7 +27,7 @@
 links [![](/are.png "my title")](http://foo.com) awesome
 
 <<<
-<p>links <a href="http://foo.com"><img src="/are.png" title="my title" /></a> awesome</p>
+<p>links <a href="http://foo.com"><img alt="" src="/are.png" title="my title" /></a> awesome</p>
 >>> no URL
 links [are]() awesome
 
diff --git a/pkgs/markdown/test/original/reference_images.unit b/pkgs/markdown/test/original/reference_images.unit
index b060da0..24dac30 100644
--- a/pkgs/markdown/test/original/reference_images.unit
+++ b/pkgs/markdown/test/original/reference_images.unit
@@ -3,7 +3,7 @@
 [foo]: http://foo.com/foo.png
 
 <<<
-<p><img src="http://foo.com/foo.png" /></p>
+<p><img alt="" src="http://foo.com/foo.png" /></p>
 >>> alternate text
 ![alternate text][foo]
 [foo]: http://foo.com/foo.png
@@ -15,13 +15,13 @@
 [foo]: http://foo.com/foo.png "optional title"
 
 <<<
-<p><img src="http://foo.com/foo.png" title="optional title" /></p>
+<p><img alt="" src="http://foo.com/foo.png" title="optional title" /></p>
 >>> invalid alt text
 ![`alt`][foo]
 [foo]: http://foo.com/foo.png "optional title"
 
 <<<
-<p><img src="http://foo.com/foo.png" title="optional title" /></p>
+<p><img alt="alt" src="http://foo.com/foo.png" title="optional title" /></p>
 >>> shortcut reference image
 ![foo]
 
diff --git a/pkgs/markdown/tool/common_mark_stats.json b/pkgs/markdown/tool/common_mark_stats.json
index 7eea678..1add705 100644
--- a/pkgs/markdown/tool/common_mark_stats.json
+++ b/pkgs/markdown/tool/common_mark_stats.json
@@ -340,23 +340,23 @@
  },
  "Images": {
   "535": true,
-  "536": false,
+  "536": true,
   "537": false,
-  "538": false,
-  "539": false,
-  "540": false,
+  "538": true,
+  "539": true,
+  "540": true,
   "541": true,
-  "542": false,
+  "542": true,
   "543": true,
-  "544": false,
+  "544": true,
   "545": true,
   "546": true,
   "547": true,
-  "548": false,
+  "548": true,
   "549": true,
   "550": true,
   "551": true,
-  "552": false,
+  "552": true,
   "553": true,
   "554": true,
   "555": true,
diff --git a/pkgs/markdown/tool/common_mark_stats.txt b/pkgs/markdown/tool/common_mark_stats.txt
index 37235da..9fae549 100644
--- a/pkgs/markdown/tool/common_mark_stats.txt
+++ b/pkgs/markdown/tool/common_mark_stats.txt
@@ -9,7 +9,7 @@
   24 of   27 –  88.9%  Fenced code blocks
   15 of   15 – 100.0%  Hard line breaks
   42 of   42 – 100.0%  HTML blocks
-  13 of   22 –  59.1%  Images
+  21 of   22 –  95.5%  Images
   10 of   12 –  83.3%  Indented code blocks
    1 of    1 – 100.0%  Inlines
   11 of   23 –  47.8%  Link reference definitions
@@ -24,4 +24,4 @@
    5 of    9 –  55.6%  Tabs
    3 of    3 – 100.0%  Textual content
   17 of   19 –  89.5%  Thematic breaks
- 449 of  616 –  72.9%  TOTAL
+ 457 of  616 –  74.2%  TOTAL