summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Seelmann2013-06-21 11:39:43 (EDT)
committerStefan Seelmann2013-06-27 16:00:50 (EDT)
commitb85fd5e471a32dce346530f1b550b9072e88cae2 (patch)
treeb662846d4d3c9f6cf3662813d71c92486721563d
parent44e446a4cd59170c6c1c62fa315a923395466072 (diff)
downloadorg.eclipse.mylyn.docs-b85fd5e471a32dce346530f1b550b9072e88cae2.zip
org.eclipse.mylyn.docs-b85fd5e471a32dce346530f1b550b9072e88cae2.tar.gz
org.eclipse.mylyn.docs-b85fd5e471a32dce346530f1b550b9072e88cae2.tar.bz2
404096: [Markdown] Add basic support for listsrefs/changes/00/14000/4
* simple ordered and unordered lists * basic line wrapping for list items * updated content assist and cheat sheet and extracted some messages Change-Id: Ib8814d69003bd874bcab055d571b8d5f2701939d Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=404096
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/internal/wikitext/markdown/core/block/ListBlock.java90
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/wikitext/markdown/core/MarkdownLanguage.java2
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageBlockElementsTest.java112
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageTest.java6
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.ui/help/cheatSheet/Markdown.md12
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.ui/plugin.properties10
-rw-r--r--org.eclipse.mylyn.wikitext.markdown.ui/plugin.xml12
7 files changed, 240 insertions, 4 deletions
diff --git a/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/internal/wikitext/markdown/core/block/ListBlock.java b/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/internal/wikitext/markdown/core/block/ListBlock.java
new file mode 100644
index 0000000..c7517f6
--- /dev/null
+++ b/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/internal/wikitext/markdown/core/block/ListBlock.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Stefan Seelmann 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:
+ * Stefan Seelmann - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.wikitext.markdown.core.block;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.mylyn.wikitext.core.parser.Attributes;
+import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.BlockType;
+
+/**
+ * Markdown lists.
+ *
+ * @author Stefan Seelmann
+ */
+public class ListBlock extends NestableBlock {
+
+ private static final Pattern itemStartPattern = Pattern.compile(" {0,3}(?:([\\*\\+\\-])|([0-9]+\\.))\\s+(.+?)"); //$NON-NLS-1$
+
+ private int blockLineCount = 0;
+
+ @Override
+ public boolean canStart(String line, int lineOffset) {
+ Matcher matcher = itemStartPattern.matcher(line.substring(lineOffset));
+ return matcher.matches();
+ }
+
+ @Override
+ protected int processLineContent(String line, int offset) {
+
+ String text = line.substring(offset);
+
+ // check start of block/item
+ String content;
+ Matcher itemStartMatcher = itemStartPattern.matcher(text);
+ if (itemStartMatcher.matches()) {
+ if (blockLineCount == 0) {
+ // start list block
+ BlockType blockType = itemStartMatcher.group(1) != null
+ ? BlockType.BULLETED_LIST
+ : BlockType.NUMERIC_LIST;
+ builder.beginBlock(blockType, new Attributes());
+ } else {
+ // end previous item
+ builder.endBlock();
+ }
+
+ // start item
+ builder.beginBlock(BlockType.LIST_ITEM, new Attributes());
+
+ // extract content
+ content = itemStartMatcher.group(3);
+ } else if (!text.trim().isEmpty()) {
+ // TODO: improve handling of wrapped lines, e.g. trim left
+ builder.characters("\n"); //$NON-NLS-1$
+ content = text;
+ } else {
+ // TODO: check for multiple paragraphs and nested blocks, for now just close the list block
+ setClosed(true);
+ return offset;
+ }
+
+ int textStart = 0;
+ markupLanguage.emitMarkupLine(getParser(), state, content, textStart);
+
+ blockLineCount++;
+ return -1;
+ }
+
+ @Override
+ public void setClosed(boolean closed) {
+ if (closed && !isClosed()) {
+ // end list item
+ builder.endBlock();
+ // end list block
+ builder.endBlock();
+ }
+ super.setClosed(closed);
+ }
+
+}
diff --git a/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/wikitext/markdown/core/MarkdownLanguage.java b/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/wikitext/markdown/core/MarkdownLanguage.java
index 54200ca..748fb49 100644
--- a/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/wikitext/markdown/core/MarkdownLanguage.java
+++ b/org.eclipse.mylyn.wikitext.markdown.core/src/org/eclipse/mylyn/wikitext/markdown/core/MarkdownLanguage.java
@@ -19,6 +19,7 @@ import org.eclipse.mylyn.internal.wikitext.markdown.core.block.HeadingBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.HorizontalRuleBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.InlineHtmlBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.LinkDefinitionBlock;
+import org.eclipse.mylyn.internal.wikitext.markdown.core.block.ListBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.ParagraphBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.QuoteBlock;
import org.eclipse.mylyn.internal.wikitext.markdown.core.block.UnderlinedHeadingBlock;
@@ -105,6 +106,7 @@ public class MarkdownLanguage extends AbstractMarkupLanguage {
blocks.add(new HeadingBlock());
blocks.add(new InlineHtmlBlock());
blocks.add(new QuoteBlock());
+ blocks.add(new ListBlock());
blocks.add(new LinkDefinitionBlock());
}
diff --git a/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageBlockElementsTest.java b/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageBlockElementsTest.java
index 1fe83cc..5fcc9dd 100644
--- a/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageBlockElementsTest.java
+++ b/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageBlockElementsTest.java
@@ -281,6 +281,18 @@ public class MarkdownLanguageBlockElementsTest extends MarkdownLanguageTestBase
parseAndAssert(markup, expectedHtml);
}
+ public void testBlockquotesContainingList() {
+ String markup = "> * Black\n> * White";
+ String expectedHtml = "<blockquote><ul><li>Black</li><li>White</li></ul></blockquote>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testBlockquotesContainingListWithWrappedItem() {
+ String markup = "> * Wrapped\n line\n> * Next\nitem";
+ String expectedHtml = "<blockquote><ul><li>Wrapped\n line</li><li>Next\nitem</li></ul></blockquote>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
public void testBlockquoteSimple() {
String markup = "> a\n> b";
String expectedHtml = "<blockquote><p>a\nb</p></blockquote>";
@@ -288,6 +300,106 @@ public class MarkdownLanguageBlockElementsTest extends MarkdownLanguageTestBase
}
/*
+ * Unordered lists use asterisks, pluses, and hyphens - interchangably - as list markers.
+ */
+ public void testUnorderedListUsingAsteriskMarker() {
+ String markup = "* Red\n* Green\n* Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testUnorderedListUsingPlusMarkers() {
+ String markup = "+ Red\n+ Green\n+ Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testUnorderedListUsingHyphenMarkers() {
+ String markup = "- Red\n- Green\n- Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testUnorderedListUsingMixedMarkers() {
+ String markup = "* Red\n- Green\n+ Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * Ordered lists use numbers followed by periods.
+ */
+ public void testOrderedListUsingSequentialNumbers() {
+ String markup = "1. Bird\n2. McHale\n3. Parish";
+ String expectedHtml = "<ol><li>Bird</li><li>McHale</li><li>Parish</li></ol>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * It's important to note that the actual numbers you use to mark the list
+ * have no effect on the HTML output Markdown produces.
+ */
+ public void testOrderedListUsingSameNumbers() {
+ String markup = "1. Bird\n1. McHale\n1. Parish";
+ String expectedHtml = "<ol><li>Bird</li><li>McHale</li><li>Parish</li></ol>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * List markers typically start at the left margin, but may be indented by up to three spaces.
+ */
+ public void testListMarkersIndentedBySpaces() {
+ String markup = " * Red\n * Green\n * Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testListMarkersIndentedByMoreThanThreeSpacesIsNotRecognizedAsList() {
+ String markup = " * Red\n * Green\n * Blue";
+ String expectedHtml = "<pre><code>* Red\n * Green\n * Blue</code></pre>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * List markers must be followed by one or more spaces or a tab.
+ */
+ public void testListMarkersFollowedBySpaces() {
+ String markup = "* Red\n* Green\n* Blue";
+ String expectedHtml = "<ul><li>Red</li><li>Green</li><li>Blue</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testListMarkersFollowedByTab() {
+ String markup = "1.\tBird\n1.\tMcHale\n1.\tParish";
+ String expectedHtml = "<ol><li>Bird</li><li>McHale</li><li>Parish</li></ol>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ public void testListMarkersNotFollowedBySpaceOrTabIsNotRecognizedAsList() {
+ String markup = "*Red\n*Green\n*Blue";
+ String expectedHtml = "<p>*Red\n*Green\n*Blue</p>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * To make lists look nice, you can wrap items with hanging indents.
+ */
+ public void testListWithWrappedItemAndHangingIndents() {
+ String markup = "* Lorem ipsum\n sit amet.\n* Donec sit\n amet nisl.";
+ String expectedHtml = "<ul><li>Lorem ipsum\n sit amet.</li><li>Donec sit\n amet nisl.</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
+ * But if you want to be lazy, you don't have to.
+ */
+ public void testListWithWrappedItemAndNoHangingIndents() {
+ String markup = "* Lorem ipsum\nsit amet.\n* Donec sit\namet nisl.";
+ String expectedHtml = "<ul><li>Lorem ipsum\nsit amet.</li><li>Donec sit\namet nisl.</li></ul>";
+ parseAndAssert(markup, expectedHtml);
+ }
+
+ /*
* Markdown wraps a code block in both pre and code tags. To produce a code block in Markdown, simply indent every
* line of the block by at least 4 spaces or 1 tab.
*/
diff --git a/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageTest.java b/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageTest.java
index ac310c6..693a615 100644
--- a/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageTest.java
+++ b/org.eclipse.mylyn.wikitext.markdown.tests/src/org/eclipse/mylyn/internal/wikitext/markdown/tests/MarkdownLanguageTest.java
@@ -37,6 +37,9 @@ public class MarkdownLanguageTest extends MarkdownLanguageTestBase {
text.append("\n");
text.append(" Code block\n");
text.append("\n");
+ text.append("* List item 1\n");
+ text.append("* List item 2\n");
+ text.append("\n");
text.append("I get 10 times more traffic from [Google] [1] than from [Yahoo][] or [MSN] [].\n");
text.append("\n");
text.append(" [1]: http://google.com/ \"Google\"\n");
@@ -54,6 +57,9 @@ public class MarkdownLanguageTest extends MarkdownLanguageTestBase {
assertTrue(html.contains("<h2>Header 2<"));
assertTrue(html.contains("<blockquote><p>Blockquote"));
assertTrue(html.contains("<pre><code>Code block"));
+ assertTrue(html.contains("<ul>"));
+ assertTrue(html.contains("<li>List item 1</li>"));
+ assertTrue(html.contains("<li>List item 2</li>"));
assertTrue(html.contains("<a href=\"http://google.com/\" title=\"Google\">Google</a>"));
assertTrue(html.contains("<a href=\"http://search.yahoo.com/\" title=\"Yahoo Search\">Yahoo</a>"));
assertTrue(html.contains("<a href=\"http://search.msn.com/\" title=\"MSN Search\">MSN</a>"));
diff --git a/org.eclipse.mylyn.wikitext.markdown.ui/help/cheatSheet/Markdown.md b/org.eclipse.mylyn.wikitext.markdown.ui/help/cheatSheet/Markdown.md
index fac847f..77b8cd2 100644
--- a/org.eclipse.mylyn.wikitext.markdown.ui/help/cheatSheet/Markdown.md
+++ b/org.eclipse.mylyn.wikitext.markdown.ui/help/cheatSheet/Markdown.md
@@ -31,6 +31,18 @@ more spaces to create a line break.
\#\# This is also an H2 \#\#
\#\#\#\#\# This is an H5
+##### Lists
+
+Unordered lists use `*`, `+`, or `-` as bullets.
+
+* one
+* two
+
+Numbered lists use numbers followed by periods:
+
+1. one
+2. two
+
##### Block Quotes
> Block quotes use email-style quoting
diff --git a/org.eclipse.mylyn.wikitext.markdown.ui/plugin.properties b/org.eclipse.mylyn.wikitext.markdown.ui/plugin.properties
index a3fedc4..7fad82f 100644
--- a/org.eclipse.mylyn.wikitext.markdown.ui/plugin.properties
+++ b/org.eclipse.mylyn.wikitext.markdown.ui/plugin.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2012 Stefan Seelmann and others.
+# Copyright (c) 2012, 2013 Stefan Seelmann 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
@@ -19,3 +19,11 @@ template.description.h3 = Heading 3
template.description.h4 = Heading 4
template.description.h5 = Heading 5
template.description.h6 = Heading 6
+template.description.lb = List (bulleted)
+template.description.ln = List (numeric)
+template.description.bq = Block quote
+template.description.li = Link (inline) - [Text](http://www.example.com "Optional title")
+template.description.lr = Link (footnote) - [Text][id]
+template.description.ls = Link (simple) - <http://www.example.com>
+template.description.ii = Image (inline) - ![Alt text](path/to/image.png "Optional title")
+template.description.ir = Image (footnote) - ![Alt text][id]
diff --git a/org.eclipse.mylyn.wikitext.markdown.ui/plugin.xml b/org.eclipse.mylyn.wikitext.markdown.ui/plugin.xml
index 9025e9a..0227fe8 100644
--- a/org.eclipse.mylyn.wikitext.markdown.ui/plugin.xml
+++ b/org.eclipse.mylyn.wikitext.markdown.ui/plugin.xml
@@ -11,9 +11,15 @@
<template name="##### " description="%template.description.h5" content="\n##### ${text}\n\n" block="true"/>
<template name="###### " description="%template.description.h6" content="\n###### ${text}\n\n" block="true"/>
- <template name="link" description="Link - [Text](http://www.example.com &quot;Optional title&quot;)" content="[${text}](${text} &quot;${title}&quot;) $"/>
- <template name="link (simple)" description="Link - &lt;http://www.example.com&gt;" content="&lt;${text}&gt; $"/>
- <template name="!image" description="Image - ![Alt text](path/to/image.png &quot;Optional title&quot;)" content="![${altText}](${text}.png &quot;${title}&quot;) $"/>
+ <template name="*" description="%template.description.lb" content="\n* ${first item}\n* ${second item}\n" block="true"/>
+ <template name="1." description="%template.description.ln" content="\n1. ${first item}\n2. ${second item}\n" block="true"/>
+ <template name="&gt;" description="%template.description.bq" content="\n&gt; ${text}\n" block="true"/>
+
+ <template name="[]" description="%template.description.li" content="[${text}](${url} &quot;${title}&quot;) $"/>
+ <template name="[id]" description="%template.description.lr" content="[${text}][${id}] ${cursor}\n\n[${id}]: ${url} &quot;${title}&quot;"/>
+ <template name="&lt;&gt;" description="%template.description.ls" content="&lt;http://${url}&gt; $"/>
+ <template name="![]" description="%template.description.ii" content="![${altText}](${image}.png &quot;${title}&quot;) $"/>
+ <template name="![id]" description="%template.description.ir" content="![${altText}][${id}] ${cursor}\n\n[${id}]: ${image}.png &quot;${title}&quot;"/>
<template name="\n" description="Line break (end of line)" content="^ \n"/>
<template name="\t" description="Code block (indented with tab)" content="\n\t${text}\n"/>