GN: Trim newlines in markdown help blocks

In markdown mode (--markdown) GN puts the actual help text into fenced blocks.
Newlines at the beginning or end of such a block are not stripped and appear
in the generated HTML output, taking up vertical space.

This change ensures that newlines at the start and end are removed.

BUG=

Review-Url: https://codereview.chromium.org/2773043005
Cr-Original-Commit-Position: refs/heads/master@{#460024}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 823f2a25b3be32ce6920072ec2b9c2d9f06ec377
diff --git a/tools/gn/command_help.cc b/tools/gn/command_help.cc
index 2d859b1..eb13456 100644
--- a/tools/gn/command_help.cc
+++ b/tools/gn/command_help.cc
@@ -87,13 +87,13 @@
       "  help on your specific command for more.\n\n");
 
   if (is_markdown)
-    OutputString("```\n\n", DECORATION_NONE);
+    OutputString("```\n", DECORATION_NONE);
 
   for (const auto& s : switches::GetSwitches())
     PrintShortHelp(s.second.short_help);
 
   if (is_markdown)
-    OutputString("\n```\n", DECORATION_NONE);
+    OutputString("```\n", DECORATION_NONE);
 
   OutputString("\n");
 }
diff --git a/tools/gn/standard_out.cc b/tools/gn/standard_out.cc
index fa347e2..8a6b7ef 100644
--- a/tools/gn/standard_out.cc
+++ b/tools/gn/standard_out.cc
@@ -251,10 +251,14 @@
 
   bool first_header = true;
   bool in_body = false;
+  std::size_t empty_lines = 0;
   for (const std::string& line : base::SplitString(
            text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
     // Check for a heading line.
     if (!line.empty() && line[0] != ' ') {
+      // New paragraph, just skip any trailing empty lines.
+      empty_lines = 0;
+
       if (is_markdown) {
         // GN's block-level formatting is converted to markdown as follows:
         // * The first heading is treated as an H3.
@@ -298,6 +302,18 @@
       in_body = true;
     }
 
+    // We buffer empty lines, so we can skip them if needed
+    // (i.e. new paragraph body, end of final paragraph body).
+    if (in_body && is_markdown) {
+      if (!line.empty() && empty_lines != 0) {
+        OutputString(std::string(empty_lines, '\n'));
+        empty_lines = 0;
+      } else if (line.empty()) {
+        ++empty_lines;
+        continue;
+      }
+    }
+
     // Check for a comment.
     TextDecoration dec = DECORATION_NONE;
     for (const auto& elem : line) {
@@ -314,6 +330,6 @@
   }
 
   if (is_markdown && in_body)
-    OutputString("\n```\n");
+    OutputString("```\n");
 }