From 32cf98472ae03172e90e374a371a1fc992c866f6 Mon Sep 17 00:00:00 2001 From: Paul Johnston Date: Tue, 22 Sep 2015 11:06:13 -0600 Subject: [PATCH 1/3] This commit adds the following: - An abstract node 'Reference' that captures the link label, title, description attributes for subclasses Link, Image, AutoLink. - AutoLink node class that allows Visitor to differentiate between inline links and types. - Support in the InlineParserImpl to capture the association between links and link reference definitions. - static Debugging functions --- .../org/commonmark/html/HtmlRenderer.java | 5 ++ .../commonmark/internal/InlineParserImpl.java | 17 ++++- .../commonmark/internal/util/Debugging.java | 58 +++++++++++++++++ .../org/commonmark/node/AbstractVisitor.java | 5 ++ .../java/org/commonmark/node/AutoLink.java | 17 +++++ .../main/java/org/commonmark/node/Image.java | 29 +-------- .../main/java/org/commonmark/node/Link.java | 29 +-------- .../java/org/commonmark/node/Reference.java | 63 ++++++++++++++++++ .../java/org/commonmark/node/Visitor.java | 2 + .../test/LinkReferenceDefinitionTest.java | 65 +++++++++++++++++++ 10 files changed, 233 insertions(+), 57 deletions(-) create mode 100644 commonmark/src/main/java/org/commonmark/internal/util/Debugging.java create mode 100644 commonmark/src/main/java/org/commonmark/node/AutoLink.java create mode 100644 commonmark/src/main/java/org/commonmark/node/Reference.java create mode 100644 commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java diff --git a/commonmark/src/main/java/org/commonmark/html/HtmlRenderer.java b/commonmark/src/main/java/org/commonmark/html/HtmlRenderer.java index a18928640..352c354f1 100644 --- a/commonmark/src/main/java/org/commonmark/html/HtmlRenderer.java +++ b/commonmark/src/main/java/org/commonmark/html/HtmlRenderer.java @@ -271,6 +271,11 @@ public void visit(IndentedCodeBlock indentedCodeBlock) { renderCodeBlock(indentedCodeBlock.getLiteral(), getAttrs(indentedCodeBlock)); } + @Override + public void visit(AutoLink link) { + visit((Link)link); + } + @Override public void visit(Link link) { Map attrs = new LinkedHashMap<>(); diff --git a/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java b/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java index ea145c595..07d7c25f4 100644 --- a/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java +++ b/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java @@ -237,6 +237,7 @@ public int parseReference(String s) { if (!referenceMap.containsKey(normalizedLabel)) { Link link = new Link(dest, title); + link.setLabel(normalizedLabel); referenceMap.put(normalizedLabel, link); } return this.pos - startPos; @@ -565,6 +566,11 @@ private boolean parseCloseBracket() { String title = null; boolean isLinkOrImage = false; + // If we are parsing a collapsed or shortcut link/image, this + // definition reference will be populated from the cached + // referenceMap. + Reference definition = null; + // Inline link? if (this.peek() == '(') { this.pos++; @@ -603,6 +609,7 @@ private boolean parseCloseBracket() { if (ref != null) { Link link = referenceMap.get(Escaping.normalizeReference(ref)); if (link != null) { + definition = link; dest = link.getDestination(); title = link.getTitle(); isLinkOrImage = true; @@ -613,7 +620,11 @@ private boolean parseCloseBracket() { if (isLinkOrImage) { // If we got here, open is a potential opener boolean isImage = opener.delimiterChar == '!'; - Node linkOrImage = isImage ? new Image(dest, title) : new Link(dest, title); + Reference linkOrImage = isImage ? new Image(dest, title) : new Link(dest, title); + if (definition != null) { + linkOrImage.setLabel(definition.getLabel()); + linkOrImage.setDefinition(definition); + } // Flush text now. We don't need to worry about combining it with adjacent text nodes, as we'll wrap it in a // link or image node. @@ -705,13 +716,13 @@ private boolean parseAutolink() { String m; if ((m = this.match(EMAIL_AUTOLINK)) != null) { String dest = m.substring(1, m.length() - 1); - Link node = new Link("mailto:" + dest, null); + Link node = new AutoLink("mailto:" + dest, null); node.appendChild(new Text(dest)); appendNode(node); return true; } else if ((m = this.match(AUTOLINK)) != null) { String dest = m.substring(1, m.length() - 1); - Link node = new Link(dest, null); + Link node = new AutoLink(dest, null); node.appendChild(new Text(dest)); appendNode(node); return true; diff --git a/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java b/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java new file mode 100644 index 000000000..8b213db9a --- /dev/null +++ b/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java @@ -0,0 +1,58 @@ +package org.commonmark.util; + +import java.util.Stack; +import org.commonmark.node.Node; + +public class Debugging { + + /** + * Print a tree-representation of the given node and its children. + */ + public static String toStringTree(Node node) { + StringBuilder b = new StringBuilder(); + Stack stack = new Stack(); + + visit(b, stack, node); + + return b.toString(); + } + + private static void visit(StringBuilder b, Stack stack, Node node) { + + int sz = stack.size(); + for (int i = 0; i < sz; i++) { + b.append('.'); + } + b.append(node.toString()); + b.append('\n'); + + Node current = node.getFirstChild(); + while (current != null) { + stack.push(current); + visit(b, stack, stack.peek()); + stack.pop(); + current = current.getNext(); + } + + } + + /** + * Log a simple message. This is not a substitute for a logging + * framework. + */ + public static void log(String msg) { + System.out.println("commonmark-java: " + msg); + } + + /** + * Print a stacktrace with the given message. + */ + public static void stacktrace(String msg) { + try { + throw new Exception(msg); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + +} diff --git a/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java b/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java index c7ecbe150..de7f8d467 100644 --- a/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java +++ b/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java @@ -78,6 +78,11 @@ public void visit(Link link) { visitChildren(link); } + @Override + public void visit(AutoLink link) { + visitChildren(link); + } + @Override public void visit(ListItem listItem) { visitChildren(listItem); diff --git a/commonmark/src/main/java/org/commonmark/node/AutoLink.java b/commonmark/src/main/java/org/commonmark/node/AutoLink.java new file mode 100644 index 000000000..521661d64 --- /dev/null +++ b/commonmark/src/main/java/org/commonmark/node/AutoLink.java @@ -0,0 +1,17 @@ +package org.commonmark.node; + +public class AutoLink extends Link { + + public AutoLink() { + super(); + } + + public AutoLink(String destination, String title) { + super(destination, title); + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/commonmark/src/main/java/org/commonmark/node/Image.java b/commonmark/src/main/java/org/commonmark/node/Image.java index 63481773a..b332a301c 100644 --- a/commonmark/src/main/java/org/commonmark/node/Image.java +++ b/commonmark/src/main/java/org/commonmark/node/Image.java @@ -1,41 +1,16 @@ package org.commonmark.node; -public class Image extends Node { - - private String destination; - private String title; +public class Image extends Reference { public Image() { } public Image(String destination, String title) { - this.destination = destination; - this.title = title; + super(destination, title); } @Override public void accept(Visitor visitor) { visitor.visit(this); } - - public String getDestination() { - return destination; - } - - public void setDestination(String destination) { - this.destination = destination; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - @Override - protected String toStringAttributes() { - return "destination=" + destination + ", title=" + title; - } } diff --git a/commonmark/src/main/java/org/commonmark/node/Link.java b/commonmark/src/main/java/org/commonmark/node/Link.java index b4794253e..87f83942a 100644 --- a/commonmark/src/main/java/org/commonmark/node/Link.java +++ b/commonmark/src/main/java/org/commonmark/node/Link.java @@ -1,41 +1,16 @@ package org.commonmark.node; -public class Link extends Node { - - private String destination; - private String title; +public class Link extends Reference { public Link() { } public Link(String destination, String title) { - this.destination = destination; - this.title = title; + super(destination, title); } @Override public void accept(Visitor visitor) { visitor.visit(this); } - - public String getDestination() { - return destination; - } - - public void setDestination(String destination) { - this.destination = destination; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - @Override - protected String toStringAttributes() { - return "destination=" + destination + ", title=" + title; - } } diff --git a/commonmark/src/main/java/org/commonmark/node/Reference.java b/commonmark/src/main/java/org/commonmark/node/Reference.java new file mode 100644 index 000000000..05438bd6b --- /dev/null +++ b/commonmark/src/main/java/org/commonmark/node/Reference.java @@ -0,0 +1,63 @@ +package org.commonmark.node; + +public abstract class Reference extends Node { + + protected Reference definition; + protected String destination; + protected String title; + protected String label; + + public Reference() { + } + + public Reference(String destination, String title) { + this.destination = destination; + this.title = title; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + /** + * If this entity represents a collapsed or shortcut link, the + * getReference method should return the link + * reference definition that the label matches to. + */ + public Reference getDefinition() { + return definition; + } + + public void setDefinition(Reference definition) { + this.definition = definition; + } + + @Override + protected String toStringAttributes() { + return "destination=" + destination + + ", title=" + title + + ", label=" + label + + ", definition=" + definition; + } + +} diff --git a/commonmark/src/main/java/org/commonmark/node/Visitor.java b/commonmark/src/main/java/org/commonmark/node/Visitor.java index 3f0b4fb6c..59591270e 100644 --- a/commonmark/src/main/java/org/commonmark/node/Visitor.java +++ b/commonmark/src/main/java/org/commonmark/node/Visitor.java @@ -35,6 +35,8 @@ public interface Visitor { void visit(Link link); + void visit(AutoLink link); + void visit(ListItem listItem); void visit(OrderedList orderedList); diff --git a/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java new file mode 100644 index 000000000..5b413cce3 --- /dev/null +++ b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java @@ -0,0 +1,65 @@ +package org.commonmark.test; + +import org.commonmark.node.Node; +import org.commonmark.node.Link; +import org.commonmark.node.AutoLink; +import org.commonmark.node.Visitor; +import org.commonmark.node.AbstractVisitor; +import org.commonmark.parser.Parser; +import org.commonmark.util.Debugging; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.commonmark.util.Debugging.log; +import static org.commonmark.util.Debugging.toStringTree; + +public class LinkReferenceDefinitionTest { + + @Test + public void one() { + + final Parser.Builder builder = Parser.builder(); + final Parser parser = builder.build(); + final Node document = parser.parse(getText()); + final java.util.List links = new java.util.ArrayList(); + + final Visitor visitor = new AbstractVisitor() { + @Override + public void visit(Link node) { + links.add(node); + } + + @Override + public void visit(AutoLink node) { + links.add(node); + } + }; + + //log(toStringTree(document)); + document.accept(visitor); + + assertEquals(3, links.size()); + + Link one = links.get(0); + Link two = links.get(1); + Link auto = links.get(2); + + assertEquals("1", one.getDefinition().getLabel()); + assertEquals("2", two.getDefinition().getLabel()); + assertEquals(AutoLink.class, auto.getClass()); + } + + String getText() { + String s = ""; + s += "* this is collapsed link: [one][1]\n"; + s += "* this is shortcut link: [2]\n"; + s += "* this is an AutoLink: ...\n"; + s += "* not to be confused with the *Autolink plugin*,"; + s += " that is not picked up in this test: http://foo.com\n"; + s += "\n"; + s += "[1]: http://1.com\n"; + s += "[2]: http://2.com\n"; + return s; + } + +} From 08dd900c593f9d2c5a1e6999df271c9354e73fbb Mon Sep 17 00:00:00 2001 From: Paul Johnston Date: Tue, 22 Sep 2015 11:45:04 -0600 Subject: [PATCH 2/3] Fixes broken test in autolink plugin and corrects package placement of Debugging.java --- .../ext/autolink/internal/AutolinkPostProcessor.java | 5 +++++ .../main/java/org/commonmark/internal/util/Debugging.java | 2 +- .../org/commonmark/test/LinkReferenceDefinitionTest.java | 5 ++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java index 33a7c321a..76165b2c0 100644 --- a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java +++ b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java @@ -61,6 +61,11 @@ private static Node insertNode(Node node, Node insertAfterNode) { private class AutolinkVisitor extends AbstractVisitor { int inLink = 0; + @Override + public void visit(AutoLink link) { + visit((Link)link); + } + @Override public void visit(Link link) { inLink++; diff --git a/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java b/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java index 8b213db9a..d1e863d5b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java +++ b/commonmark/src/main/java/org/commonmark/internal/util/Debugging.java @@ -1,4 +1,4 @@ -package org.commonmark.util; +package org.commonmark.internal.util; import java.util.Stack; import org.commonmark.node.Node; diff --git a/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java index 5b413cce3..ac55eed57 100644 --- a/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java +++ b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionTest.java @@ -6,12 +6,11 @@ import org.commonmark.node.Visitor; import org.commonmark.node.AbstractVisitor; import org.commonmark.parser.Parser; -import org.commonmark.util.Debugging; import org.junit.Test; import static org.junit.Assert.assertEquals; -import static org.commonmark.util.Debugging.log; -import static org.commonmark.util.Debugging.toStringTree; +import static org.commonmark.internal.util.Debugging.log; +import static org.commonmark.internal.util.Debugging.toStringTree; public class LinkReferenceDefinitionTest { From 75d62ae4e3be013185338e84f9ecb1e1824c1e5b Mon Sep 17 00:00:00 2001 From: Paul Johnston Date: Tue, 22 Sep 2015 12:54:40 -0600 Subject: [PATCH 3/3] Adds support for introspection on the delimiter character and length for inline elements emphasis (italic), strong emphasis (bold), and strikethrough nodes. New interface 'Delimited' can be implemented by other custom node classes with similar behaviour. --- .../ext/gfm/strikethrough/Strikethrough.java | 22 +++++- .../StrikethroughDelimiterProcessor.java | 2 +- .../inline/EmphasisDelimiterProcessor.java | 5 +- .../java/org/commonmark/node/Delimited.java | 9 +++ .../java/org/commonmark/node/Emphasis.java | 20 +++++- .../org/commonmark/node/StrongEmphasis.java | 21 +++++- .../org/commonmark/test/DelimitedTest.java | 69 +++++++++++++++++++ 7 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 commonmark/src/main/java/org/commonmark/node/Delimited.java create mode 100644 commonmark/src/test/java/org/commonmark/test/DelimitedTest.java diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java index b4ecfce2f..1d89594de 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java @@ -1,9 +1,29 @@ package org.commonmark.ext.gfm.strikethrough; import org.commonmark.node.CustomNode; +import org.commonmark.node.Delimited; /** * A strikethrough node containing text and other inline nodes nodes as children. */ -public class Strikethrough extends CustomNode { +public class Strikethrough extends CustomNode implements Delimited { + + private final char delimiterChar; + private final int delimiterCount; + + public Strikethrough(char delimiterChar, int delimiterCount) { + this.delimiterChar = delimiterChar; + this.delimiterCount = delimiterCount; + } + + @Override + public char getDelimiterChar() { + return delimiterChar; + } + + @Override + public int getDelimiterCount() { + return delimiterCount; + } + } diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java index 14a847e2d..3e9b71efc 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java @@ -39,7 +39,7 @@ public void process(Text opener, Text closer, int delimiterCount) { } // Normal case, wrap nodes between delimiters in strikethrough. - Node strikethrough = new Strikethrough(); + Node strikethrough = new Strikethrough(getDelimiterChar(), delimiterCount); Node tmp = opener.getNext(); while (tmp != null && tmp != closer) { diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java b/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java index 3e83dd7a9..5532c816a 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java @@ -1,6 +1,7 @@ package org.commonmark.internal.inline; import org.commonmark.parser.DelimiterProcessor; +import org.commonmark.node.Delimited; import org.commonmark.node.Emphasis; import org.commonmark.node.Node; import org.commonmark.node.StrongEmphasis; @@ -26,7 +27,9 @@ public int getDelimiterUse(int openerCount, int closerCount) { @Override public void process(Text opener, Text closer, int delimiterUse) { - Node emphasis = delimiterUse == 1 ? new Emphasis() : new StrongEmphasis(); + Node emphasis = delimiterUse == 1 + ? new Emphasis(getDelimiterChar(), delimiterUse) + : new StrongEmphasis(getDelimiterChar(), delimiterUse); Node tmp = opener.getNext(); while (tmp != null && tmp != closer) { diff --git a/commonmark/src/main/java/org/commonmark/node/Delimited.java b/commonmark/src/main/java/org/commonmark/node/Delimited.java new file mode 100644 index 000000000..dc65a772a --- /dev/null +++ b/commonmark/src/main/java/org/commonmark/node/Delimited.java @@ -0,0 +1,9 @@ +package org.commonmark.node; + +public interface Delimited { + + char getDelimiterChar(); + + int getDelimiterCount(); + +} diff --git a/commonmark/src/main/java/org/commonmark/node/Emphasis.java b/commonmark/src/main/java/org/commonmark/node/Emphasis.java index 3f7c86051..39069de04 100644 --- a/commonmark/src/main/java/org/commonmark/node/Emphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/Emphasis.java @@ -1,6 +1,24 @@ package org.commonmark.node; -public class Emphasis extends Node { +public class Emphasis extends Node implements Delimited { + + private final char delimiterChar; + private final int delimiterCount; + + public Emphasis(char delimiterChar, int delimiterCount) { + this.delimiterChar = delimiterChar; + this.delimiterCount = delimiterCount; + } + + @Override + public char getDelimiterChar() { + return delimiterChar; + } + + @Override + public int getDelimiterCount() { + return delimiterCount; + } @Override public void accept(Visitor visitor) { diff --git a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java index 26ab4fbf5..eeb9e9343 100644 --- a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java @@ -1,9 +1,28 @@ package org.commonmark.node; -public class StrongEmphasis extends Node { +public class StrongEmphasis extends Node implements Delimited { + + private char delimiterChar; + private int delimiterCount; + + public StrongEmphasis(char delimiterChar, int delimiterCount) { + this.delimiterChar = delimiterChar; + this.delimiterCount = delimiterCount; + } + + @Override + public char getDelimiterChar() { + return delimiterChar; + } + + @Override + public int getDelimiterCount() { + return delimiterCount; + } @Override public void accept(Visitor visitor) { visitor.visit(this); } + } diff --git a/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java b/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java new file mode 100644 index 000000000..813192bdc --- /dev/null +++ b/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java @@ -0,0 +1,69 @@ +package org.commonmark.test; + +import org.commonmark.node.Node; +import org.commonmark.node.Delimited; +import org.commonmark.node.Emphasis; +import org.commonmark.node.StrongEmphasis; +import org.commonmark.node.Visitor; +import org.commonmark.node.AbstractVisitor; +import org.commonmark.parser.Parser; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.commonmark.internal.util.Debugging.log; +import static org.commonmark.internal.util.Debugging.toStringTree; + +public class DelimitedTest { + + @Test + public void one() { + + final Parser.Builder builder = Parser.builder(); + final Parser parser = builder.build(); + final Node document = parser.parse(getText()); + final java.util.List list = new java.util.ArrayList(); + + final Visitor visitor = new AbstractVisitor() { + @Override + public void visit(Emphasis node) { + list.add(node); + } + + @Override + public void visit(StrongEmphasis node) { + list.add(node); + } + }; + + //log(toStringTree(document)); + document.accept(visitor); + + assertEquals(4, list.size()); + + Delimited emphasis = list.get(0); + Delimited strong = list.get(1); + Delimited important = list.get(2); + Delimited critical = list.get(3); + + assertEquals('*', emphasis.getDelimiterChar()); + assertEquals('*', strong.getDelimiterChar()); + assertEquals('_', important.getDelimiterChar()); + assertEquals('_', critical.getDelimiterChar()); + + assertEquals(1, emphasis.getDelimiterCount()); + assertEquals(2, strong.getDelimiterCount()); + assertEquals(1, important.getDelimiterCount()); + assertEquals(2, critical.getDelimiterCount()); + + } + + String getText() { + String s = ""; + s += "* *emphasis* \n"; + s += "* **strong** \n"; + s += "* _important_ \n"; + s += "* __CRITICAL__ \n"; + return s; + } + +}