diff options
author | James Kennedy | 2017-03-17 17:38:27 +0000 |
---|---|---|
committer | James Kennedy | 2017-04-05 22:21:15 +0000 |
commit | 4b6ee285eeb087b6a2abfad78b4d98e96de426af (patch) | |
tree | 20fb1b0df4c3314d8e70a5d885301887407c4b8e | |
parent | 17aaa90a9959b9584d0196b62d2f484c2d75151c (diff) | |
download | org.eclipse.mylyn.docs-4b6ee285eeb087b6a2abfad78b4d98e96de426af.tar.gz org.eclipse.mylyn.docs-4b6ee285eeb087b6a2abfad78b4d98e96de426af.tar.xz org.eclipse.mylyn.docs-4b6ee285eeb087b6a2abfad78b4d98e96de426af.zip |
513661: Confluence TableBlock supports multi-line content
Allows cell content to cross the end-of-line boundary.
Change-Id: I400f0bf64ae82b2fe23e55f5ce210721cd4ab6ab
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=513661
Signed-off-by: James Kennedy <james.kennedy@tasktop.com>
3 files changed, 86 insertions, 17 deletions
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/TableBlock.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/TableBlock.java index 34a1e115c..ffe7c21d3 100644 --- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/TableBlock.java +++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/TableBlock.java @@ -29,6 +29,8 @@ import com.google.common.collect.ImmutableList; */ public class TableBlock extends Block { + private static final int LINE_PROCESSED_INDICATOR = -1; + private static final List<Class<?>> NESTABLE_CELL_BLOCKS = ImmutableList.of(ListBlock.class); private static final Pattern START_PATTERN = Pattern.compile("\\s*(\\|\\|?.*$)"); //$NON-NLS-1$ @@ -52,29 +54,63 @@ public class TableBlock extends Block { private boolean rowStarted = false; + private boolean multiLineCell = false; + public TableBlock() { } @Override public int processLineContent(String line, int offset) { nesting = false; + int finalOffset = processLineStart(line, offset); + + if (isClosed() || finalOffset == LINE_PROCESSED_INDICATOR) { + return isClosed() ? 0 : LINE_PROCESSED_INDICATOR; + } + + ++blockLineCount; + + if (atEndOfRow(line, finalOffset)) { + ensureRowClosed(); + finalOffset = LINE_PROCESSED_INDICATOR; + } else { + finalOffset = processCellContent(line, finalOffset); + } + + return isClosed() ? 0 : processEndOfLine(line, finalOffset); + } + + private int processLineStart(String line, int offset) { if (blockLineCount == 0) { Attributes attributes = new Attributes(); builder.beginBlock(BlockType.TABLE, attributes); } else if (markupLanguage.isEmptyLine(line)) { setClosed(true); - return 0; + } else if (offset == 0 && multiLineCell) { + offset = continueMultiLineCell(line, offset); + } else if (!TABLE_ROW_PATTERN.matcher(line).find()) { + setClosed(true); } + return offset; + } - ++blockLineCount; - - if (atEndOfRow(line, offset)) { - ensureRowClosed(); - return -1; + private int continueMultiLineCell(String line, int offset) { + String cellContent = line; + Matcher rowMatcher = TABLE_ROW_PATTERN.matcher(line); + if (rowMatcher.find()) { + offset = rowMatcher.start(); + if (offset > 0) { + cellContent = line.substring(0, offset); + builder.lineBreak(); + emitMarkup(cellContent, 0); + } + ensureCellClosed(); + } else { + builder.lineBreak(); + emitMarkup(cellContent, 0); + return LINE_PROCESSED_INDICATOR; } - - int postCellOffset = processCellContent(line, offset); - return isClosed() ? 0 : processEndOfLine(line, postCellOffset); + return offset; } private boolean atEndOfRow(String line, int lineOffset) { @@ -127,11 +163,15 @@ public class TableBlock extends Block { } private int processEndOfLine(String line, int offset) { - if (!nesting) { - ensureRowClosed(); - return -1; + if (offset != LINE_PROCESSED_INDICATOR && !nesting) { + if (atEndOfRow(line, offset)) { + ensureRowClosed(); + return LINE_PROCESSED_INDICATOR; + } else { + multiLineCell = true; + } } - return offset >= line.length() ? -1 : offset; + return offset >= line.length() ? LINE_PROCESSED_INDICATOR : offset; } @Override @@ -191,6 +231,7 @@ public class TableBlock extends Block { if (currentCell != null) { builder.endBlock(); currentCell = null; + multiLineCell = false; } } } diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageIntegrationTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageIntegrationTest.java index ca7464344..765b8ad2d 100644 --- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageIntegrationTest.java +++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageIntegrationTest.java @@ -32,10 +32,15 @@ public class ConfluenceLanguageIntegrationTest { } @Test - // test for bug# 513661 public void listsInTables() { - String textile = "|* item 1\n* item 2|# item 3\n# item 4|"; - assertRoundTrip(textile, textile); + assertRoundTripExact("|* item 1\n* item 2|# item 3\n# item 4|\n\n"); + } + + @Test + public void tableWithMultiLineCellContent() { + String table = "|line one\\\\line two\\\\line three|\n\n"; + assertRoundTripExact(table); + assertRoundTrip("|line one\nline two\nline three|", table); } private void assertHtmlToConfluence(boolean parseAsDocument) { @@ -53,6 +58,10 @@ public class ConfluenceLanguageIntegrationTest { assertEquals("some text *bold here* more text\n\n", confluenceOut.toString()); } + private void assertRoundTripExact(String textile) { + assertRoundTrip(textile, textile); + } + private void assertRoundTrip(String textileIn, String textileOut) { Writer confluenceOut = new StringWriter(); ConfluenceLanguage confluenceLanguage = new ConfluenceLanguage(); @@ -61,6 +70,6 @@ public class ConfluenceLanguageIntegrationTest { parser.setBuilder(confluenceLanguage.createDocumentBuilder(confluenceOut)); parser.parse(textileIn, false); - assertEquals(textileOut, confluenceOut.toString().trim()); + assertEquals(textileOut, confluenceOut.toString()); } } diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageTest.java index 3b59374e3..4bd56998a 100644 --- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageTest.java +++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageTest.java @@ -656,6 +656,25 @@ public class ConfluenceLanguageTest extends AbstractMarkupGenerationTest<Conflue } @Test + public void testTableWithMultilineText() { + assertMarkup("<table><tr><td>label</td><td>line1<br/>line2<br/>line3</td><td>text</td></tr></table>", + "|label|line1\nline2\nline3|text |"); + } + + @Test + public void testTableWithMultilineTextImplicitEnd() { + assertMarkup("<table><tr><td>label</td><td>line1<br/>line2<br/>line3</td></tr></table><p>text</p>", + "|label|line1\nline2\nline3\n\ntext"); + } + + @Test + public void testTableWithMultilineTextAndNestedBlock() { + assertMarkup( + "<table><tr><td><ul><li>listitem</li></ul></td><td>line1<br/>line2<br/>line3</td><td><ul><li>listitem2</li></ul></td></tr></table>", + "|* listitem|line1\nline2\nline3|* listitem2|"); + } + + @Test public void testTableWithHeader() { assertMarkup( "<table><tr><th>a</th><th>header</th><th>row</th></tr><tr><td>a</td><td>row</td><td>not header</td></tr></table>", |