@@ -25,6 +25,7 @@ | |||
<module>sonar-graph</module> | |||
<module>sonar-gwt-api</module> | |||
<module>sonar-java-api</module> | |||
<module>sonar-markdown</module> | |||
<module>sonar-maven-plugin</module> | |||
<module>sonar-maven3-plugin</module> | |||
<module>sonar-plugin-api</module> |
@@ -1,5 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>org.codehaus.sonar</groupId> | |||
@@ -20,15 +21,20 @@ | |||
<groupId>org.slf4j</groupId> | |||
<artifactId>slf4j-api</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.hamcrest</groupId> | |||
<artifactId>hamcrest-all</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.hamcrest</groupId> | |||
<artifactId>hamcrest-all</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>ch.qos.logback</groupId> | |||
<artifactId>logback-classic</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -20,6 +20,7 @@ | |||
package org.sonar.channel; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import org.slf4j.Logger; | |||
@@ -34,13 +35,18 @@ public class ChannelDispatcher<OUTPUT> extends Channel<OUTPUT> { | |||
private final Channel[] channels; | |||
@SuppressWarnings("rawtypes") | |||
public ChannelDispatcher(List<Channel> tokenizers) { | |||
this(tokenizers, false); | |||
public ChannelDispatcher(List<Channel> channels) { | |||
this(channels, false); | |||
} | |||
@SuppressWarnings("rawtypes") | |||
public ChannelDispatcher(List<Channel> tokenizers, boolean failIfNoChannelToConsumeOneCharacter) { | |||
this.channels = tokenizers.toArray(new Channel[0]); // NOSONAR, lack of performance is not an issue here | |||
public ChannelDispatcher(Channel... channels) { | |||
this(Arrays.asList(channels), false); | |||
} | |||
@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.failIfNoChannelToConsumeOneCharacter = failIfNoChannelToConsumeOneCharacter; | |||
} | |||
@@ -0,0 +1,43 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>org.codehaus.sonar</groupId> | |||
<artifactId>sonar</artifactId> | |||
<version>2.8-SNAPSHOT</version> | |||
<relativePath>..</relativePath> | |||
</parent> | |||
<artifactId>sonar-markdown</artifactId> | |||
<name>Sonar :: Markdown</name> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.codehaus.sonar</groupId> | |||
<artifactId>sonar-channel</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>commons-io</groupId> | |||
<artifactId>commons-io</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.slf4j</groupId> | |||
<artifactId>slf4j-api</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>ch.qos.logback</groupId> | |||
<artifactId>logback-classic</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.hamcrest</groupId> | |||
<artifactId>hamcrest-all</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -0,0 +1,32 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import org.sonar.channel.Channel; | |||
import org.sonar.channel.CodeReader; | |||
class BlackholeChannel extends Channel<MarkdownOutput> { | |||
@Override | |||
public boolean consume(CodeReader code, MarkdownOutput output) { | |||
output.append((char)code.pop()); | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import org.sonar.channel.RegexChannel; | |||
class HtmlEmphasisChannel extends RegexChannel<MarkdownOutput> { | |||
public HtmlEmphasisChannel() { | |||
super("\\*[^\n\r]*\\*"); | |||
} | |||
@Override | |||
protected void consume(CharSequence token, MarkdownOutput output) { | |||
output.append("<em>" + token.subSequence(1, token.length() - 1) + "</em>"); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import org.sonar.channel.RegexChannel; | |||
class HtmlEndOfLineChannel extends RegexChannel<MarkdownOutput> { | |||
public HtmlEndOfLineChannel() { | |||
super("(\r?\n)|(\r)"); | |||
} | |||
@Override | |||
protected void consume(CharSequence token, MarkdownOutput output) { | |||
output.append("<br/>"); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import org.sonar.channel.RegexChannel; | |||
class HtmlUrlChannel extends RegexChannel<MarkdownOutput> { | |||
public HtmlUrlChannel() { | |||
super("https?://[\\w\\d:#@%/;$()~_?\\+-=\\.&]*"); | |||
} | |||
@Override | |||
protected void consume(CharSequence token, MarkdownOutput output) { | |||
output.append("<a href=\"" +token + "\">" + token + "</a>"); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import org.sonar.channel.RegexChannel; | |||
class IdentifierAndNumberChannel extends RegexChannel<MarkdownOutput> { | |||
public IdentifierAndNumberChannel() { | |||
super("[\\p{Alpha}\\d]++"); | |||
} | |||
@Override | |||
protected void consume(CharSequence token, MarkdownOutput output) { | |||
output.append(token); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.sonar.channel.Channel; | |||
import org.sonar.channel.ChannelDispatcher; | |||
import org.sonar.channel.CodeReader; | |||
public class MarkdownEngine { | |||
private MarkdownOutput output; | |||
private ChannelDispatcher<MarkdownOutput> dispatcher; | |||
private MarkdownEngine() { | |||
output = new MarkdownOutput(); | |||
List<Channel> markdownChannels = new ArrayList<Channel>(); | |||
markdownChannels.add(new HtmlUrlChannel()); | |||
markdownChannels.add(new HtmlEndOfLineChannel()); | |||
markdownChannels.add(new HtmlEmphasisChannel()); | |||
markdownChannels.add(new IdentifierAndNumberChannel()); | |||
markdownChannels.add(new BlackholeChannel()); | |||
dispatcher = new ChannelDispatcher<MarkdownOutput>(markdownChannels); | |||
} | |||
public static String convertToHtml(String input) { | |||
MarkdownEngine engine = new MarkdownEngine(); | |||
engine.dispatcher.consume(new CodeReader(input), engine.output); | |||
return engine.output.toString(); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
class MarkdownOutput { | |||
private StringBuilder ouput = new StringBuilder(); | |||
public Appendable append(CharSequence charSequence) { | |||
return ouput.append(charSequence); | |||
} | |||
public Appendable append(char character) { | |||
return ouput.append(character); | |||
} | |||
public String toString() { | |||
return ouput.toString(); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
/* | |||
* Sonar, open source software quality management 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 | |||
*/ | |||
package org.sonar.markdown; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import org.junit.Test; | |||
public class MarkdownEngineTest { | |||
@Test | |||
public void shouldDecorateUrl() { | |||
assertThat(MarkdownEngine.convertToHtml("http://google.com"), is("<a href=\"http://google.com\">http://google.com</a>")); | |||
} | |||
@Test | |||
public void shouldDecorateEndOfLine() { | |||
assertThat(MarkdownEngine.convertToHtml("1\r2\r\n3\n"), is("1<br/>2<br/>3<br/>")); | |||
} | |||
@Test | |||
public void shouldEmphaseText() { | |||
assertThat(MarkdownEngine.convertToHtml("This is *important*"), is("This is <em>important</em>")); | |||
assertThat(MarkdownEngine.convertToHtml("This should not be * \n emphase"), is("This should not be * <br/> emphase")); | |||
} | |||
@Test | |||
public void shouldNotChangeAnythingInTheText() { | |||
assertThat(MarkdownEngine.convertToHtml("My text is $123 ''"), is("My text is $123 ''")); | |||
} | |||
} |