]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2384 Support markdown in review comments
authorsimonbrandhof <simon.brandhof@gmail.com>
Sat, 23 Apr 2011 16:18:10 +0000 (18:18 +0200)
committersimonbrandhof <simon.brandhof@gmail.com>
Sat, 23 Apr 2011 16:35:26 +0000 (18:35 +0200)
12 files changed:
pom.xml
sonar-channel/src/main/java/org/sonar/channel/ChannelDispatcher.java
sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java
sonar-server/pom.xml
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/markdown_helper.rb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/models/review_comment.rb
sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_review.html.erb
sonar-server/src/main/webapp/stylesheets/style.css

diff --git a/pom.xml b/pom.xml
index 9e4210fab3b77db799628824cf865576eadb3eff..624f72a7ae94670015acc4cc8addcc0de966ab14 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <artifactId>sonar-channel</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.codehaus.sonar</groupId>
+        <artifactId>sonar-markdown</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.codehaus.sonar</groupId>
         <artifactId>sonar-check-api</artifactId>
index d772d81ffd5450babba58774fb42f218992c1539..dcbd5c56a7476a8cbd323012010e64fd695d2839 100644 (file)
@@ -46,7 +46,7 @@ public class ChannelDispatcher<OUTPUT> extends Channel<OUTPUT> {
 
   @SuppressWarnings("rawtypes")
   public ChannelDispatcher(List<Channel> channels, boolean failIfNoChannelToConsumeOneCharacter) {
-    this.channels = channels.toArray(new Channel[0]); // NOSONAR, lack of performance is not an issue here
+    this.channels = channels.toArray(new Channel[channels.size()]);
     this.failIfNoChannelToConsumeOneCharacter = failIfNoChannelToConsumeOneCharacter;
   }
 
index 25ad180b4b3fb2ec1060f6ff884fea8d8f03587e..2358e0bfa4457a60ced2dce097505a29442f7016 100644 (file)
@@ -258,9 +258,9 @@ public class CodeBuffer implements CharSequence {
   public final String toString() {
     StringBuilder result = new StringBuilder();
     result.append("CodeReader(");
-    result.append("line:" + cursor.line);
-    result.append("|column:" + cursor.column);
-    result.append("|cursor value:'" + (char) peek() + "'");
+    result.append("line:").append(cursor.line);
+    result.append("|column:").append(cursor.column);
+    result.append("|cursor value:'").append((char) peek()).append("'");
     result.append(")");
     return result.toString();
   }
index 5927afa3eaeee4bb12390c46c727a973f740069b..5b5e2fa614da5ccb3424a6bb9d0bebd4d66556d3 100644 (file)
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-java-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-markdown</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.codehaus.sonar</groupId>
index 5c680ab91bcae67b2c595850114baf854d9d6d55..972017928b34129f64e29b36b8d1a52daff74360 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.api.web.*;
 import org.sonar.jpa.dao.AsyncMeasuresService;
 import org.sonar.jpa.dialect.Dialect;
 import org.sonar.jpa.session.DatabaseConnector;
+import org.sonar.markdown.MarkdownEngine;
 import org.sonar.server.configuration.Backup;
 import org.sonar.server.configuration.CoreConfiguration;
 import org.sonar.server.configuration.ProfilesManager;
@@ -64,7 +65,7 @@ public final class JRubyFacade {
     return getContainer().getComponent(FilterExecutor.class).execute(filter);
   }
 
-  /* UPDATE CENTER */
+  // UPDATE CENTER ------------------------------------------------------------
 
   public void downloadPlugin(String pluginKey, String pluginVersion) {
     getContainer().getComponent(PluginDownloader.class).download(pluginKey, Version.create(pluginVersion));
@@ -94,7 +95,7 @@ public final class JRubyFacade {
     return getContainer().getComponent(UpdateCenterMatrixFactory.class).getMatrix(forceReload);
   }
 
-  /* PLUGINS */
+  // PLUGINS ------------------------------------------------------------------
 
   public Property[] getPluginProperties(PluginMetadata metadata) {
     Plugins plugins = getContainer().getComponent(Plugins.class);
@@ -109,6 +110,9 @@ public final class JRubyFacade {
     return getContainer().getComponent(PluginDeployer.class).getPluginsMetadata();
   }
 
+
+  // SYNTAX HIGHLIGHTING ------------------------------------------------------
+
   public String colorizeCode(String code, String language) {
     try {
       return getContainer().getComponent(CodeColorizers.class).toHtml(code, language);
@@ -119,6 +123,14 @@ public final class JRubyFacade {
     }
   }
 
+  public static String markdownToHtml(String input) {
+    return MarkdownEngine.convertToHtml(input);
+  }
+
+
+
+  
+
   public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage) {
     return getContainer().getComponent(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage);
   }
index 4c2f796a5dd7e635ad6f1760103e36042fbfb60f..4e2215565094a5a83b683c9025cb113e4a6d0465 100644 (file)
@@ -20,7 +20,7 @@
 class ResourceController < ApplicationController
 
   SECTION=Navigation::SECTION_RESOURCE
-  helper DashboardHelper
+  helper :dashboard, :markdown
   
   def index
     @resource = Project.by_key(params[:id])
index 55bd4c558967449706b84462771c3fac0d9f1fa3..d7d038e98df9e9fb4da38c5c53424d809f0ebc8c 100644 (file)
@@ -24,6 +24,8 @@ class ReviewsController < ApplicationController
 
   verify :method => :post, :only => [  :create, :create_comment ], :redirect_to => { :action => :error_not_post }
 
+  helper(:reviews, :markdown)
+  
   def index
     init_params
     search_reviews
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/markdown_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/markdown_helper.rb
new file mode 100644 (file)
index 0000000..bd4f648
--- /dev/null
@@ -0,0 +1,26 @@
+ #
+ # Sonar, entreprise quality control tool.
+ # Copyright (C) 2008-2011 SonarSource
+ # mailto:contact AT sonarsource DOT com
+ #
+ # Sonar 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.
+ #
+ # Sonar 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 Sonar; if not, write to the Free Software
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ #
+module MarkdownHelper
+
+  def markdown_to_html(input)
+    input ? Java::OrgSonarServerUi::JRubyFacade.markdownToHtml(h(input)) : ''
+  end
+
+end
\ No newline at end of file
index 51e07df0043500b6400ab7c9f0fc9ca1ef4b5161..c690fd5ff4f48f756fdbb7463088bdfc03b70e24 100644 (file)
@@ -23,6 +23,10 @@ class ReviewComment < ActiveRecord::Base
   validates_presence_of :user => "can't be empty"
   validate :comment_should_not_be_empty
   
+  alias_attribute :text, :review_text
+    
+  private
+  
   def comment_should_not_be_empty
     errors.add("Comment", " cannot be empty") if review_text.strip.blank?
   end
index 84b476fa9ac99e9912c34946ea234be2773f37b5..4d52a57dcfec8224ccca992e1ef571fc6abedfc4 100644 (file)
     </h4> 
       <% if review_comment == last_comment %>
         <div id="lastComment<%= violation.id -%>">
-          <%= h(review_comment.review_text) -%>
+          <%= markdown_to_html(review_comment.text) -%>
         </div>
       <% else %>
-        <%= h(review_comment.review_text) -%>
+        <%= markdown_to_html(review_comment.text) -%>
       <% end %>
   </div>
   <% 
 </div>
 <% end %>
 
-<div>
\ No newline at end of file
+</div>
\ No newline at end of file
index 35407e6eb7a5b2933af137d038ca43fadd979b07..970a328bfee7df22a2f9b4b05eddad2f966646c9 100644 (file)
                <%= review.assignee ? h(review.assignee.name) : '-'-%>
           </td>
           <td class="key">
-                 Created
+                 Created by:
           </td>
           <td  class="val">
-                 by <%= h(review.user.name) -%> at <%= l(review.created_at) -%>
+                 <%= h(review.user.name) -%> at <%= l(review.created_at) -%>
           </td>
         </tr>
        <% if review.rule %>
@@ -68,8 +68,8 @@
         <% review.comments.each do |comment| %>
           <div class="discussionComment">
                 <h4><%= image_tag("reviews/comment.png") -%> &nbsp;<b><%= comment.user.name -%></b> (<%= distance_of_time_in_words_to_now(comment.created_at) -%>)</h4>
-           <%= h(comment.review_text) -%>
+           <%= markdown_to_html(comment.text) -%>
           </div>
         <% end %>
   </div>
-<div>
\ No newline at end of file
+</div>
\ No newline at end of file
index 52d2e3bd5e01e2fd7aa0b7d2450a1a8d07061a7e..ed955431b8745f8018a0bfa7f0ade96d1d640e0f 100644 (file)
@@ -289,11 +289,14 @@ code {
 .small {
   font-size: 85%;
 }
-em {
+small {
   color: #AAA;
   font-size: 85%;
   font-style: normal;
 }
+em {
+  font-weight: bold;
+}
 
 a.external {
        background: url('../images/links/external.png') no-repeat 100% 0;