<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>
<?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>
<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>
\ No newline at end of file
package org.sonar.channel;
+import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
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;
}
--- /dev/null
+<?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>
\ No newline at end of file
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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>");
+ }
+}
--- /dev/null
+/*
+ * 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/>");
+ }
+}
--- /dev/null
+/*
+ * 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>");
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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 ''"));
+ }
+
+}