From 330652c2f62c2704c73cef85db822c4c2d02ebca Mon Sep 17 00:00:00 2001 From: Paul Johnston Date: Tue, 22 Sep 2015 12:54:40 -0600 Subject: [PATCH 1/2] 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; + } + +} From c6424daa1f11f0112da5a6b442dad6bced6e0079 Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Wed, 3 Feb 2016 19:51:24 +1100 Subject: [PATCH 2/2] Change Delimited interface to allow for asymmetric delimiters --- .../ext/gfm/strikethrough/Strikethrough.java | 17 ++-- .../StrikethroughDelimiterProcessor.java | 2 +- .../gfm/strikethrough/StrikethroughTest.java | 11 +++ .../inline/EmphasisDelimiterProcessor.java | 8 +- .../java/org/commonmark/node/Delimited.java | 14 +++- .../java/org/commonmark/node/Emphasis.java | 23 +++--- .../org/commonmark/node/StrongEmphasis.java | 24 +++--- .../org/commonmark/test/DelimitedTest.java | 81 ++++++++----------- 8 files changed, 93 insertions(+), 87 deletions(-) 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 1d89594de..115ae9ea4 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 @@ -8,22 +8,15 @@ */ 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; - } + private static final String DELIMITER = "~~"; @Override - public char getDelimiterChar() { - return delimiterChar; + public String getOpeningDelimiter() { + return DELIMITER; } @Override - public int getDelimiterCount() { - return delimiterCount; + public String getClosingDelimiter() { + return DELIMITER; } - } 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 3e9b71efc..14a847e2d 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(getDelimiterChar(), delimiterCount); + Node strikethrough = new Strikethrough(); Node tmp = opener.getNext(); while (tmp != null && tmp != closer) { diff --git a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java index d65c1557d..12bcf2a49 100644 --- a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java +++ b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java @@ -2,6 +2,7 @@ import org.commonmark.Extension; import org.commonmark.html.HtmlRenderer; +import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.test.RenderingTestCase; import org.junit.Test; @@ -9,6 +10,8 @@ import java.util.Collections; import java.util.Set; +import static org.junit.Assert.assertEquals; + public class StrikethroughTest extends RenderingTestCase { private static final Set EXTENSIONS = Collections.singleton(StrikethroughExtension.create()); @@ -63,6 +66,14 @@ public void insideBlockQuote() { "
\n

strike that

\n
\n"); } + @Test + public void delimited() { + Node document = PARSER.parse("~~foo~~"); + Strikethrough strikethrough = (Strikethrough) document.getFirstChild().getFirstChild(); + assertEquals("~~", strikethrough.getOpeningDelimiter()); + assertEquals("~~", strikethrough.getClosingDelimiter()); + } + @Override protected String render(String source) { return RENDERER.render(PARSER.parse(source)); 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 5532c816a..1b9ebc371 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java @@ -1,11 +1,10 @@ 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; import org.commonmark.node.Text; +import org.commonmark.parser.DelimiterProcessor; public abstract class EmphasisDelimiterProcessor implements DelimiterProcessor { @@ -27,9 +26,10 @@ public int getDelimiterUse(int openerCount, int closerCount) { @Override public void process(Text opener, Text closer, int delimiterUse) { + String singleDelimiter = String.valueOf(getDelimiterChar()); Node emphasis = delimiterUse == 1 - ? new Emphasis(getDelimiterChar(), delimiterUse) - : new StrongEmphasis(getDelimiterChar(), delimiterUse); + ? new Emphasis(singleDelimiter) + : new StrongEmphasis(singleDelimiter + singleDelimiter); 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 index dc65a772a..ef02c84ad 100644 --- a/commonmark/src/main/java/org/commonmark/node/Delimited.java +++ b/commonmark/src/main/java/org/commonmark/node/Delimited.java @@ -1,9 +1,17 @@ package org.commonmark.node; +/** + * A node that uses delimiters in the source form (e.g. *bold*). + */ public interface Delimited { - char getDelimiterChar(); - - int getDelimiterCount(); + /** + * @return the opening (beginning) delimiter, e.g. * + */ + String getOpeningDelimiter(); + /** + * @return the closing (ending) delimiter, e.g. * + */ + String getClosingDelimiter(); } diff --git a/commonmark/src/main/java/org/commonmark/node/Emphasis.java b/commonmark/src/main/java/org/commonmark/node/Emphasis.java index 39069de04..9877e7b63 100644 --- a/commonmark/src/main/java/org/commonmark/node/Emphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/Emphasis.java @@ -2,22 +2,27 @@ public class Emphasis extends Node implements Delimited { - private final char delimiterChar; - private final int delimiterCount; + private String delimiter; - public Emphasis(char delimiterChar, int delimiterCount) { - this.delimiterChar = delimiterChar; - this.delimiterCount = delimiterCount; + public Emphasis() { + } + + public Emphasis(String delimiter) { + this.delimiter = delimiter; + } + + public void setDelimiter(String delimiter) { + this.delimiter = delimiter; } @Override - public char getDelimiterChar() { - return delimiterChar; + public String getOpeningDelimiter() { + return delimiter; } @Override - public int getDelimiterCount() { - return delimiterCount; + public String getClosingDelimiter() { + return delimiter; } @Override diff --git a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java index eeb9e9343..dbff571cd 100644 --- a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java @@ -2,27 +2,31 @@ public class StrongEmphasis extends Node implements Delimited { - private char delimiterChar; - private int delimiterCount; + private String delimiter; - public StrongEmphasis(char delimiterChar, int delimiterCount) { - this.delimiterChar = delimiterChar; - this.delimiterCount = delimiterCount; + public StrongEmphasis() { + } + + public StrongEmphasis(String delimiter) { + this.delimiter = delimiter; + } + + public void setDelimiter(String delimiter) { + this.delimiter = delimiter; } @Override - public char getDelimiterChar() { - return delimiterChar; + public String getOpeningDelimiter() { + return delimiter; } @Override - public int getDelimiterCount() { - return delimiterCount; + public String getClosingDelimiter() { + return delimiter; } @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 index 813192bdc..a34a32c44 100644 --- a/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java +++ b/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java @@ -1,41 +1,38 @@ 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.node.*; import org.commonmark.parser.Parser; import org.junit.Test; +import java.util.ArrayList; +import java.util.List; + 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)); + public void emphasisDelimiters() { + String input = "* *emphasis* \n" + + "* **strong** \n" + + "* _important_ \n" + + "* __CRITICAL__ \n"; + + Parser parser = Parser.builder().build(); + Node document = parser.parse(input); + + final List list = new ArrayList<>(); + Visitor visitor = new AbstractVisitor() { + @Override + public void visit(Emphasis node) { + list.add(node); + } + + @Override + public void visit(StrongEmphasis node) { + list.add(node); + } + }; document.accept(visitor); assertEquals(4, list.size()); @@ -45,25 +42,13 @@ public void visit(StrongEmphasis node) { 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; + assertEquals("*", emphasis.getOpeningDelimiter()); + assertEquals("*", emphasis.getClosingDelimiter()); + assertEquals("**", strong.getOpeningDelimiter()); + assertEquals("**", strong.getClosingDelimiter()); + assertEquals("_", important.getOpeningDelimiter()); + assertEquals("_", important.getClosingDelimiter()); + assertEquals("__", critical.getOpeningDelimiter()); + assertEquals("__", critical.getClosingDelimiter()); } - }