Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Nosworthy2018-10-17 21:21:49 +0000
committerRyan Nosworthy2018-10-17 23:30:31 +0000
commitb643f7d1d505b4f979b178a2cba99b17bec8a748 (patch)
treec7487988c43e675cd56f7944f84f7f7a231b5ab4
parent1d7c17eca3001f4d96e5653ca13a139933bf5e9e (diff)
downloadorg.eclipse.mylyn.docs-b643f7d1d505b4f979b178a2cba99b17bec8a748.tar.gz
org.eclipse.mylyn.docs-b643f7d1d505b4f979b178a2cba99b17bec8a748.tar.xz
org.eclipse.mylyn.docs-b643f7d1d505b4f979b178a2cba99b17bec8a748.zip
540235: ExtendedQuoteBlock supports nested blocks over multiple lines
* Override the three functions necessary for nested block supported as specified in the Block javadocs: beginNesting(), findClosedOffset(), and canResume(). This way we can leverage the logic within AbstractMarkupLanguage that manages the state of nested blocks. * Further in order for AbstractMarkupLanguage to supported ExtendedQuoteBlock and its nested blocks it needs to know what the offset is for the current line being processed. Currently the abstract function in AbstractConfluenceDelimitedBlock assumes the whole line being processed and has a void return. This is not the case so we should return an offset when calling handleBlockContent(). * Added tests for the transformation of Confluence markup to HTML * Added tests for the transformation of HTML document building blocks to Confluence markup https://bugs.eclipse.org/bugs/show_bug.cgi?id=540235 Change-Id: Ic11a7605fc0bbca3c97a6e432a4036834faafd33 Signed-off-by: Ryan Nosworthy <ryan.nosworthy@tasktop.com>
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/AbstractConfluenceDelimitedBlock.java39
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/CodeBlock.java5
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedPreformattedBlock.java7
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlock.java39
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/ConfluenceLanguageTest.java14
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/ConfluenceDocumentBuilderTest.java22
-rw-r--r--wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlockTest.java37
7 files changed, 139 insertions, 24 deletions
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/AbstractConfluenceDelimitedBlock.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/AbstractConfluenceDelimitedBlock.java
index 21c347f00..b6cfbf1a6 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/AbstractConfluenceDelimitedBlock.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/AbstractConfluenceDelimitedBlock.java
@@ -40,38 +40,57 @@ public abstract class AbstractConfluenceDelimitedBlock extends ParameterizedBloc
beginBlock();
}
- int end = line.length();
- int segmentEnd = end;
+ int endOfContent = line.length();
+ int segmentEnd = endOfContent;
boolean terminating = false;
- if (offset < end) {
+ if (offset < endOfContent) {
Matcher endMatcher = endPattern.matcher(line);
if (blockLineCount == 0) {
- endMatcher.region(offset, end);
+ endMatcher.region(offset, endOfContent);
}
if (endMatcher.find()) {
terminating = true;
- end = endMatcher.start(2);
+ endOfContent = endMatcher.start(2);
segmentEnd = endMatcher.start(1);
}
}
- if (end < line.length()) {
- state.setLineSegmentEndOffset(end);
+ if (endOfContent < line.length()) {
+ state.setLineSegmentEndOffset(endOfContent);
}
++blockLineCount;
final String content = line.substring(offset, segmentEnd);
- handleBlockContent(content);
+ int contentOffset = handleBlockContent(content);
if (terminating) {
setClosed(true);
}
- return end == line.length() ? -1 : end;
+
+ return finalOffset(line.length(), endOfContent, contentOffset);
+ }
+
+ private int finalOffset(int lineLength, int endOfContent, int contentOffset) {
+ int finalOffset = contentOffset;
+ if (contentOffset == lineLength) {
+ finalOffset = -1;
+ } else if (endOfContent != lineLength) {
+ finalOffset = endOfContent;
+ }
+ return finalOffset;
}
- protected abstract void handleBlockContent(String content);
+ /**
+ * Process the given line of markup starting at the provided offset.
+ *
+ * @param line
+ * the markup line to process
+ * @return a non-negative integer to indicate that processing of the block completed before the end of the line, or
+ * -1 if the entire line was processed.
+ */
+ protected abstract int handleBlockContent(String content);
protected abstract void beginBlock();
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/CodeBlock.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/CodeBlock.java
index ce6cd315f..ff824b93c 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/CodeBlock.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/CodeBlock.java
@@ -44,15 +44,16 @@ public class CodeBlock extends AbstractConfluenceDelimitedBlock {
}
@Override
- protected void handleBlockContent(String content) {
+ protected int handleBlockContent(String content) {
builder.characters(content);
builder.characters("\n"); //$NON-NLS-1$
+ return -1;
}
@Override
protected void endBlock() {
if (title != null) {
- builder.endBlock(); // panel
+ builder.endBlock(); // panel
}
builder.endBlock(); // code
}
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedPreformattedBlock.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedPreformattedBlock.java
index 152825362..9eef784ae 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedPreformattedBlock.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedPreformattedBlock.java
@@ -18,7 +18,7 @@ import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.BlockType;
/**
* quoted text block, matches blocks that start with <code>{noformat}</code>. Creates an extended block type of
* {@link ParagraphBlock paragraph}.
- *
+ *
* @author David Green
*/
public class ExtendedPreformattedBlock extends AbstractConfluenceDelimitedBlock {
@@ -39,13 +39,14 @@ public class ExtendedPreformattedBlock extends AbstractConfluenceDelimitedBlock
}
@Override
- protected void handleBlockContent(String content) {
+ protected int handleBlockContent(String content) {
if (content.length() > 0) {
builder.characters(content);
} else if (blockLineCount == 1) {
- return;
+ return -1;
}
builder.characters("\n"); //$NON-NLS-1$
+ return -1;
}
@Override
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlock.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlock.java
index 041af8154..9f7cfcce3 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlock.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/main/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlock.java
@@ -20,7 +20,7 @@ import org.eclipse.mylyn.wikitext.parser.markup.Block;
/**
* quoted text block, matches blocks that start with <code>{quote}</code>. Creates an extended block type of
* {@link ParagraphBlock paragraph}.
- *
+ *
* @author David Green
*/
public class ExtendedQuoteBlock extends AbstractConfluenceDelimitedBlock {
@@ -64,7 +64,7 @@ public class ExtendedQuoteBlock extends AbstractConfluenceDelimitedBlock {
}
@Override
- protected void handleBlockContent(String content) {
+ protected int handleBlockContent(String content) {
if (nestedBlock == null) {
ConfluenceLanguage markupLanguage = (ConfluenceLanguage) getMarkupLanguage();
for (Block block : markupLanguage.getNestedBlocks()) {
@@ -87,22 +87,19 @@ public class ExtendedQuoteBlock extends AbstractConfluenceDelimitedBlock {
nestedBlock = null;
}
if (lineOffset < content.length() && lineOffset >= 0) {
- if (nestedBlock != null) {
- throw new IllegalStateException("if a block does not fully process a line then it must be closed"); //$NON-NLS-1$
- }
- content = content.substring(lineOffset);
+ return lineOffset;
} else {
- return;
+ return -1;
}
}
if (blockLineCount == 1 && content.length() == 0) {
- return;
+ return -1;
}
if (blockLineCount > 1 && paraOpen && getMarkupLanguage().isEmptyLine(content)) {
builder.endBlock(); // para
paraOpen = false;
paraLine = 0;
- return;
+ return -1;
}
if (!paraOpen) {
builder.beginBlock(BlockType.PARAGRAPH, new Attributes());
@@ -113,7 +110,31 @@ public class ExtendedQuoteBlock extends AbstractConfluenceDelimitedBlock {
}
++paraLine;
getMarkupLanguage().emitMarkupLine(getParser(), state, content, 0);
+ return -1;
+ }
+
+ @Override
+ public int findCloseOffset(String line, int lineOffset) {
+ if (nestedBlock == null) {
+ return super.findCloseOffset(line, lineOffset);
+ }
+ return nestedBlock.findCloseOffset(line, lineOffset);
+ }
+ @Override
+ public boolean beginNesting() {
+ if (nestedBlock == null) {
+ return super.beginNesting();
+ }
+ return nestedBlock.beginNesting();
+ }
+
+ @Override
+ public boolean canResume(String line, int lineOffset) {
+ if (nestedBlock == null) {
+ return super.canResume(line, lineOffset);
+ }
+ return nestedBlock.canResume(line, lineOffset);
}
@Override
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 a89b23437..ab2897eca 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
@@ -150,6 +150,20 @@ public class ConfluenceLanguageTest extends AbstractMarkupGenerationTest<Conflue
}
@Test
+ public void testBlockQuoteExtendedWithNestedTable() {
+ assertMarkup(
+ "<blockquote><table><tr><td>Names</td><td>Occupation</td></tr><tr><td><ul><li>John</li><li>Jane</li></ul></td><td>Programmer</td></tr></table></blockquote>",
+ "{quote}|Names|Occupation|\n|* John\n* Jane|Programmer|{quote}\n");
+ }
+
+ @Test
+ public void testBlockQuoteExtendedWithMultipleNestedBlocks() {
+ assertMarkup(
+ "<blockquote><table><tr><td>Names</td><td>Occupation</td></tr><tr><td><ul><li>John</li><li>Jane</li></ul></td><td>Programmer</td></tr></table><ul><li>another</li><li>list</li></ul><p>and a para</p></blockquote>",
+ "{quote}\n|Names|Occupation|\n|* John\n* Jane|Programmer|\n\n* another\n* list\n\nand a para{quote}\n");
+ }
+
+ @Test
public void testSimplePhraseModifiers() throws IOException {
Object[][] pairs = new Object[][] { { "*", "strong" }, { "_", "em" }, { "??", "cite" }, { "-", "del" },
{ "+", "u" }, { "^", "sup" }, { "~", "sub" }, };
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/ConfluenceDocumentBuilderTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/ConfluenceDocumentBuilderTest.java
index ed3a6e108..8b4f61209 100644
--- a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/ConfluenceDocumentBuilderTest.java
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/ConfluenceDocumentBuilderTest.java
@@ -660,6 +660,28 @@ public class ConfluenceDocumentBuilderTest {
}
@Test
+ public void nestTablesAfterBlockQuote() {
+ builder.beginDocument();
+ builder.beginBlock(BlockType.QUOTE, new Attributes());
+ builder.beginBlock(BlockType.TABLE, new Attributes());
+ builder.beginBlock(BlockType.TABLE_ROW, new Attributes());
+ builder.beginBlock(BlockType.TABLE_CELL_NORMAL, new Attributes());
+ builder.beginBlock(BlockType.BULLETED_LIST, new Attributes());
+ emitListItemHavingParagraphAndContent("first");
+ emitListItemHavingParagraphAndContent("second");
+ builder.endBlock();
+ builder.endBlock();
+ builder.endBlock();
+ builder.endBlock();
+ builder.endBlock();
+ builder.endDocument();
+
+ String markup = out.toString();
+
+ assertEquals("{quote}|* first\n* second|\n\n{quote}\n\n", markup);
+ }
+
+ @Test
public void tableWithNestedList() {
assertTableRow("| |* first\n" + //
"* second| |\n\n", //
diff --git a/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlockTest.java b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlockTest.java
new file mode 100644
index 000000000..e392fa3c1
--- /dev/null
+++ b/wikitext/core/org.eclipse.mylyn.wikitext.confluence/src/test/java/org/eclipse/mylyn/wikitext/confluence/internal/block/ExtendedQuoteBlockTest.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 David Green and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * David Green - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.wikitext.confluence.internal.block;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class ExtendedQuoteBlockTest {
+
+ @Test
+ public void beginNestingWithoutANestedBlock() {
+ ExtendedQuoteBlock block = new ExtendedQuoteBlock();
+ assertEquals(false, block.beginNesting());
+ }
+
+ @Test
+ public void canResumeWithoutANestedBlock() {
+ ExtendedQuoteBlock block = new ExtendedQuoteBlock();
+ assertEquals(false, block.canResume("some line", 1));
+ }
+
+ @Test
+ public void finadCloseOffsetWithoutANestBlock() {
+ ExtendedQuoteBlock block = new ExtendedQuoteBlock();
+ assertEquals(-1, block.findCloseOffset("some line", 1));
+ }
+}

Back to the top