542496: Add support for Code Blocks and Spans to the Creole
DocumentBuilder

Change-Id: I0bc2906504c1d1e11272d4f0f63f70fb4c1d738f
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=542496
Signed-off-by: Kevin de Vlaming <kevin.devlaming@tasktop.com>
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/main/java/org/eclipse/mylyn/wikitext/creole/internal/CreoleDocumentBuilder.java b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/main/java/org/eclipse/mylyn/wikitext/creole/internal/CreoleDocumentBuilder.java
index 6b69943..fef3c23 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/main/java/org/eclipse/mylyn/wikitext/creole/internal/CreoleDocumentBuilder.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/main/java/org/eclipse/mylyn/wikitext/creole/internal/CreoleDocumentBuilder.java
@@ -181,6 +181,9 @@
 			return new ContentBlock(type, computePrefix(prefixChar, computeListLevel()) + " ", "", 1, 1);
 		case PARAGRAPH:
 			return new ContentBlock(type, "", "", 2, 2); //$NON-NLS-1$ //$NON-NLS-2$
+		case PREFORMATTED:
+		case CODE:
+			return new ContentBlock(type, "{{{\n", "\n}}}", 2, 2); //$NON-NLS-1$ //$NON-NLS-2$
 		case TABLE:
 			return new SuffixBlock(type, "\n"); //$NON-NLS-1$
 		case TABLE_CELL_HEADER:
@@ -222,6 +225,8 @@
 			return new ContentBlock("**", "**"); //$NON-NLS-1$ //$NON-NLS-2$
 		case DELETED:
 			return new ContentBlock("--", "--"); //$NON-NLS-1$ //$NON-NLS-2$
+		case CODE:
+			return new ContentBlock("{{{", "}}}"); //$NON-NLS-1$ //$NON-NLS-2$
 		case UNDERLINED:
 			return new ContentBlock("__", "__"); //$NON-NLS-1$ //$NON-NLS-2$
 		default:
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderBlockTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderBlockTest.java
index 4ac6299..8ca273d 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderBlockTest.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderBlockTest.java
@@ -109,6 +109,90 @@
 		assertMarkup("text\n\n**bold** text\n\n");
 	}
 
+	public void testBlockCode() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.CODE, new Attributes());
+		builder.characters("text\n\nmore text");
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("{{{\ntext\n\nmore text\n}}}\n\n", markup);
+	}
+
+	public void testCodeBlockWithLineBreaks() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.CODE, new Attributes());
+		builder.characters("line 1");
+		builder.lineBreak();
+		builder.characters("line 2");
+		builder.lineBreak();
+		builder.lineBreak();
+		builder.characters("line 3");
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("{{{\nline 1\\\\line 2\\\\\\\\line 3\n}}}\n\n", markup);
+	}
+
+	public void testCodeBlockCurlyBraceContent() {
+		assertCodeBlock("{{{\n{something}\n}}}\n\n", "{something}");
+	}
+
+	public void testCodeBlockSquareBraceContent() {
+		assertCodeBlock("{{{\n[something]\n}}}\n\n", "[something]");
+	}
+
+	public void testPreformattedBlockWithLineBreaks() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.PREFORMATTED, new Attributes());
+		builder.characters("line 1");
+		builder.lineBreak();
+		builder.characters("line 2");
+		builder.lineBreak();
+		builder.lineBreak();
+		builder.characters("line 3");
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("{{{\nline 1\\\\line 2\\\\\\\\line 3\n}}}\n\n", markup);
+	}
+
+	public void testPreformattedBlockWithCurlyBraceContent() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.PREFORMATTED, new Attributes());
+		builder.characters("{somecontent}");
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("{{{\n{somecontent}\n}}}\n\n", markup);
+	}
+
+	public void testParagraphFollowingExtendedBlockCode() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.CODE, new Attributes());
+		builder.characters("text\n\nmore text");
+		builder.endBlock();
+		builder.beginBlock(BlockType.PARAGRAPH, new Attributes());
+		builder.characters("text");
+		builder.endBlock();
+		builder.beginBlock(BlockType.PARAGRAPH, new Attributes());
+		builder.characters("text2");
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("{{{\ntext\n\nmore text\n}}}\n\ntext\n\ntext2\n\n", markup);
+	}
+
 	public void testEmptyBlock() {
 		builder.beginDocument();
 		builder.beginBlock(BlockType.PARAGRAPH, new Attributes());
@@ -126,4 +210,16 @@
 		assertMarkup("unsupported\n\n");
 	}
 
+	private void assertCodeBlock(String expected, String content) {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.CODE, new Attributes());
+		builder.characters(content);
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals(expected, markup);
+	}
+
 }
\ No newline at end of file
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderListTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderListTest.java
index d5f98a1..fee565c 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderListTest.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderListTest.java
@@ -15,6 +15,7 @@
 
 import org.eclipse.mylyn.wikitext.parser.Attributes;
 import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.BlockType;
+import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.SpanType;
 
 /**
  * @see http://www.wikicreole.org/wiki/Elements
@@ -95,6 +96,30 @@
 		assertMarkup("* X\n\n* Y\n\n* Z\n\n");
 	}
 
+	public void testListWithCodeSpan() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.BULLETED_LIST, new Attributes());
+
+		builder.beginBlock(BlockType.LIST_ITEM, new Attributes());
+		builder.characters("No code");
+		builder.endBlock();
+
+		builder.beginBlock(BlockType.BULLETED_LIST, new Attributes());
+
+		builder.beginBlock(BlockType.LIST_ITEM, new Attributes());
+		builder.characters("With ");
+		builder.beginSpan(SpanType.CODE, new Attributes());
+		builder.characters("* /code\\ *");
+		builder.endSpan();
+		builder.endBlock();
+
+		builder.endBlock();
+
+		builder.endBlock();
+		builder.endDocument();
+		assertMarkup("* No code\n** With {{{* /code\\ *}}}\n");
+	}
+
 	public void testBulletedListWithNestedSublist() {
 		builder.beginDocument();
 
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderSpanTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderSpanTest.java
index 554b9b4..2432a3f 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderSpanTest.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderSpanTest.java
@@ -85,6 +85,15 @@
 		assertMarkup("__underlined__\n\n");
 	}
 
+	public void testCode() {
+		builder.beginDocument();
+		builder.beginSpan(SpanType.CODE, new Attributes());
+		builder.characters("code");
+		builder.endSpan();
+		builder.endDocument();
+		assertMarkup("{{{code}}}\n\n");
+	}
+
 	public void testEmptySpan() {
 		builder.beginDocument();
 		builder.characters("prefix");
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderTableTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderTableTest.java
index 4d686a9..7cf056e 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderTableTest.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.creole/src/test/java/org/eclipse/mylyn/internal/wikitext/creole/tests/documentbuilder/CreoleDocumentBuilderTableTest.java
@@ -80,7 +80,6 @@
 		ImageAttributes attr = new ImageAttributes();
 		attr.setAlt("Alt text");
 		builder.image(attr, "/path/to/img.jpg");
-		builder.endDocument();
 		builder.endBlock();
 
 		builder.endBlock();
@@ -92,6 +91,32 @@
 		assertEquals("|{{/path/to/img.jpg}}|{{/path/to/img.jpg|Alt text}}|\n\n", markup);
 	}
 
+	public void testTableWithCodeSpan() {
+		builder.beginDocument();
+		builder.beginBlock(BlockType.TABLE, new Attributes());
+
+		builder.beginBlock(BlockType.TABLE_ROW, new Attributes());
+
+		builder.beginBlock(BlockType.TABLE_CELL_NORMAL, new Attributes());
+		builder.characters("No code");
+		builder.endBlock();
+
+		builder.beginBlock(BlockType.TABLE_CELL_NORMAL, new Attributes());
+		builder.characters("With ");
+		builder.beginSpan(SpanType.CODE, new Attributes());
+		builder.characters("* | /code\\ | *");
+		builder.endSpan();
+		builder.endBlock();
+
+		builder.endBlock();
+		builder.endBlock();
+		builder.endDocument();
+
+		String markup = out.toString();
+
+		assertEquals("|No code|With {{{* | /code\\ | *}}}|\n\n", markup);
+	}
+
 	private void assertTableRow(String expectedMarkup, BlockType cellType) {
 		assertTableRow(expectedMarkup, cellType, () -> builder.characters("content"));
 	}