]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4681 Add support for blockquote
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 9 May 2014 10:28:47 +0000 (12:28 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 9 May 2014 13:15:52 +0000 (15:15 +0200)
sonar-markdown/src/main/java/org/sonar/markdown/HtmlBlockquoteChannel.java [new file with mode: 0644]
sonar-markdown/src/main/java/org/sonar/markdown/Markdown.java
sonar-markdown/src/test/java/org/sonar/markdown/MarkdownTest.java

diff --git a/sonar-markdown/src/main/java/org/sonar/markdown/HtmlBlockquoteChannel.java b/sonar-markdown/src/main/java/org/sonar/markdown/HtmlBlockquoteChannel.java
new file mode 100644 (file)
index 0000000..c236e15
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.markdown;
+
+import org.sonar.channel.Channel;
+import org.sonar.channel.CodeReader;
+import org.sonar.channel.RegexChannel;
+
+/**
+ * Markdown treats lines starting with a greater than sign (&gt;) as a block of quoted text.
+ *
+ * E.g, the input:
+ * <pre>
+ * &gt; Yesterday it worked
+ * &gt; Today it is not working
+ * &gt; Software is like that
+ * </pre>
+ * will produce:
+ * {@literal<blockquote>}{@literal<p>}Yesterday it worked{@literal<br/>}
+ * Today it is not working{@literal<br/>}
+ * Software is like that{@literal</blockquote>}
+ * @since 4.4
+ */
+class HtmlBlockquoteChannel extends Channel<MarkdownOutput> {
+
+  private QuotedLineElementChannel quotedLineElement = new QuotedLineElementChannel();
+  private EndOfLine endOfLine = new EndOfLine();
+  private boolean pendingBlockConstruction;
+
+  @Override
+  public boolean consume(CodeReader code, MarkdownOutput output) {
+    try {
+      if (code.getColumnPosition() == 0) {
+        if (quotedLineElement.consume(code, output)) {
+          while (endOfLine.consume(code, output) && quotedLineElement.consume(code, output)) {
+            // consume input
+          }
+          output.append("</blockquote>");
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      pendingBlockConstruction = false;
+    }
+  }
+
+  private class QuotedLineElementChannel extends RegexChannel<MarkdownOutput> {
+
+    protected QuotedLineElementChannel() {
+      super(">\\s[^\r\n]*+");
+    }
+
+    @Override
+    protected void consume(CharSequence token, MarkdownOutput output) {
+      if (!pendingBlockConstruction) {
+        output.append("<blockquote>");
+        pendingBlockConstruction = true;
+      }
+      output.append(token.subSequence(searchIndexOfFirstCharacter(token), token.length()));
+      output.append("<br/>");
+    }
+
+    private int searchIndexOfFirstCharacter(CharSequence token) {
+      for (int index = 0; index < token.length(); index++) {
+        if (token.charAt(index) == '>') {
+          while (++ index < token.length()) {
+            if (token.charAt(index) != ' ') {
+              return index;
+            }
+          }
+        }
+      }
+      return token.length() - 1;
+    }
+  }
+
+  private static final class EndOfLine extends RegexChannel<MarkdownOutput> {
+
+    public EndOfLine() {
+      super("(\r?\n)|(\r)");
+    }
+
+    @Override
+    protected void consume(CharSequence token, MarkdownOutput output) {
+      output.append(token);
+    }
+  }
+}
index 79f3c939d8491e9aa49a1c02ac78fb05a914f5f7..acdb58a6ebdf28f07f04b8e2bd612bb39a758528 100644 (file)
@@ -35,6 +35,7 @@ public final class Markdown {
       .addChannel(new HtmlEndOfLineChannel())
       .addChannel(new HtmlEmphasisChannel())
       .addChannel(new HtmlListChannel())
+      .addChannel(new HtmlBlockquoteChannel())
       .addChannel(new HtmlHeadingChannel())
       .addChannel(new HtmlCodeChannel())
       .addChannel(new HtmlMultilineCodeChannel())
index d2e78c4d4d0387ad09f999dd53169345ed881954..0f96cf2a59f56542fe2a43b403887314decc7e2b 100644 (file)
@@ -58,6 +58,11 @@ public class MarkdownTest {
         .isEqualTo("<h1>Top\r</h1><h2>Sub\r\n</h2><h3>Subsub\n</h3><h4></h4> 1.five");
   }
 
+  @Test
+  public void shouldDecorateBlockquote() {
+    assertThat(Markdown.convertToHtml("> Yesterday it worked\n> Today it is not working\r\n> Software is like that\r"))
+        .isEqualTo("<blockquote>Yesterday it worked<br/>\nToday it is not working<br/>\r\nSoftware is like that<br/>\r</blockquote>");
+  }
 
   @Test
   public void shouldDecorateMixedOrderedAndUnorderedList() {