From 30532f9e1d8f42f6f1bb161106fa3ff5e8bcf584 Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Mon, 24 Dec 2018 13:22:31 +0300 Subject: [PATCH] Configure strikethrough extension artifact --- markwon-ext-strikethrough/README.md | 29 ++++ markwon-ext-strikethrough/build.gradle | 8 ++ markwon-ext-strikethrough/gradle.properties | 3 + .../strikethrough/StrikethroughPlugin.java | 10 +- .../StrikethroughPluginTest.java | 129 ++++++++++++++++++ markwon/build.gradle | 1 - .../ru/noties/markwon/core/MarkwonTheme.java | 3 +- 7 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 markwon-ext-strikethrough/README.md create mode 100644 markwon-ext-strikethrough/gradle.properties create mode 100644 markwon-ext-strikethrough/src/test/java/ru/noties/markwon/ext/strikethrough/StrikethroughPluginTest.java diff --git a/markwon-ext-strikethrough/README.md b/markwon-ext-strikethrough/README.md new file mode 100644 index 00000000..55b9e542 --- /dev/null +++ b/markwon-ext-strikethrough/README.md @@ -0,0 +1,29 @@ +# Strikethrough + +[![markwon-ext-strikethrough](https://img.shields.io/maven-central/v/ru.noties/markwon-ext-strikethrough.svg?label=markwon-ext-strikethrough)](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%22markwon-ext-strikethrough%22) + +This module adds `strikethrough` functionality to `Markwon` via `StrikethroughPlugin`: + +```java +Markwon.builder(context) + .usePlugin(StrikethroughPlugin.create()) +``` + +This plugin registers `SpanFactory` for `Strikethrough` node, so it's possible to customize Strikethrough Span that is used in rendering: + +```java +Markwon.builder(context) + .usePlugin(StrikethroughPlugin.class) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { + builder.setFactory(Strikethrough.class, new SpanFactory() { + @Override + public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) { + // will use Underline span instead of Strikethrough + return new UnderlineSpan(); + } + }); + } + }) +``` \ No newline at end of file diff --git a/markwon-ext-strikethrough/build.gradle b/markwon-ext-strikethrough/build.gradle index b4daa0d1..3490b416 100644 --- a/markwon-ext-strikethrough/build.gradle +++ b/markwon-ext-strikethrough/build.gradle @@ -20,6 +20,14 @@ dependencies { deps.with { api it['commonmark-strikethrough'] } + + deps.test.with { + testImplementation project(':markwon-test-span') + testImplementation it['junit'] + testImplementation it['mockito'] + testImplementation it['robolectric'] + testImplementation it['ix-java'] + } } registerArtifact(this) \ No newline at end of file diff --git a/markwon-ext-strikethrough/gradle.properties b/markwon-ext-strikethrough/gradle.properties new file mode 100644 index 00000000..86d609ac --- /dev/null +++ b/markwon-ext-strikethrough/gradle.properties @@ -0,0 +1,3 @@ +POM_NAME=Markwon-Ext-Strikethrough +POM_ARTIFACT_ID=markwon-ext-strikethrough +POM_PACKAGING=aar \ No newline at end of file diff --git a/markwon-ext-strikethrough/src/main/java/ru/noties/markwon/ext/strikethrough/StrikethroughPlugin.java b/markwon-ext-strikethrough/src/main/java/ru/noties/markwon/ext/strikethrough/StrikethroughPlugin.java index 96b76672..f73ccc71 100644 --- a/markwon-ext-strikethrough/src/main/java/ru/noties/markwon/ext/strikethrough/StrikethroughPlugin.java +++ b/markwon-ext-strikethrough/src/main/java/ru/noties/markwon/ext/strikethrough/StrikethroughPlugin.java @@ -16,6 +16,14 @@ import ru.noties.markwon.MarkwonVisitor; import ru.noties.markwon.RenderProps; import ru.noties.markwon.SpanFactory; +/** + * Plugin to add strikethrough markdown feature. This plugin will extend commonmark-java.Parser + * with strikethrough extension, add SpanFactory and register commonmark-java.Strikethrough node + * visitor + * + * @see #create() + * @since 3.0.0 + */ public class StrikethroughPlugin extends AbstractMarkwonPlugin { @NonNull @@ -45,7 +53,7 @@ public class StrikethroughPlugin extends AbstractMarkwonPlugin { public void visit(@NonNull MarkwonVisitor visitor, @NonNull Strikethrough strikethrough) { final int length = visitor.length(); visitor.visitChildren(strikethrough); - visitor.setSpansForNode(strikethrough, length); + visitor.setSpansForNodeOptional(strikethrough, length); } }); } diff --git a/markwon-ext-strikethrough/src/test/java/ru/noties/markwon/ext/strikethrough/StrikethroughPluginTest.java b/markwon-ext-strikethrough/src/test/java/ru/noties/markwon/ext/strikethrough/StrikethroughPluginTest.java new file mode 100644 index 00000000..18cab664 --- /dev/null +++ b/markwon-ext-strikethrough/src/test/java/ru/noties/markwon/ext/strikethrough/StrikethroughPluginTest.java @@ -0,0 +1,129 @@ +package ru.noties.markwon.ext.strikethrough; + +import android.support.annotation.NonNull; +import android.text.style.StrikethroughSpan; + +import org.commonmark.Extension; +import org.commonmark.ext.gfm.strikethrough.Strikethrough; +import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension; +import org.commonmark.parser.Parser; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +import ix.Ix; +import ru.noties.markwon.AbstractMarkwonPlugin; +import ru.noties.markwon.Markwon; +import ru.noties.markwon.MarkwonConfiguration; +import ru.noties.markwon.MarkwonSpansFactory; +import ru.noties.markwon.MarkwonVisitor; +import ru.noties.markwon.RenderProps; +import ru.noties.markwon.SpanFactory; +import ru.noties.markwon.core.CorePlugin; +import ru.noties.markwon.test.TestSpan; +import ru.noties.markwon.test.TestSpanMatcher; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static ru.noties.markwon.test.TestSpan.document; +import static ru.noties.markwon.test.TestSpan.span; +import static ru.noties.markwon.test.TestSpan.text; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class StrikethroughPluginTest { + + @Test + public void plugin_parser_extension_registered() { + // configure parser is called with proper parser extension + + final StrikethroughPlugin plugin = StrikethroughPlugin.create(); + final Parser.Builder parserBuilder = mock(Parser.Builder.class); + plugin.configureParser(parserBuilder); + + //noinspection unchecked + final ArgumentCaptor> captor = ArgumentCaptor.forClass(Iterable.class); + + //noinspection unchecked + verify(parserBuilder, times(1)).extensions(captor.capture()); + + final List list = Ix.from(captor.getValue()).toList(); + assertEquals(1, list.size()); + + assertTrue(list.get(0) instanceof StrikethroughExtension); + } + + @Test + public void plugin_span_factory_registered() { + // strikethrough has proper spanFactory registered + + final StrikethroughPlugin plugin = StrikethroughPlugin.create(); + final MarkwonSpansFactory.Builder spansFactoryBuilder = mock(MarkwonSpansFactory.Builder.class); + plugin.configureSpansFactory(spansFactoryBuilder); + + final ArgumentCaptor captor = ArgumentCaptor.forClass(SpanFactory.class); + + verify(spansFactoryBuilder, times(1)) + .setFactory(eq(Strikethrough.class), captor.capture()); + + assertTrue(captor.getValue().getSpans(mock(MarkwonConfiguration.class), mock(RenderProps.class)) instanceof StrikethroughSpan); + } + + @Test + public void plugin_node_visitor_registered() { + // visit has strikethrough node visitor registered + + final StrikethroughPlugin plugin = StrikethroughPlugin.create(); + final MarkwonVisitor.Builder visitorBuilder = mock(MarkwonVisitor.Builder.class); + plugin.configureVisitor(visitorBuilder); + + final ArgumentCaptor captor = + ArgumentCaptor.forClass(MarkwonVisitor.NodeVisitor.class); + + //noinspection unchecked + verify(visitorBuilder, times(1)).on(eq(Strikethrough.class), captor.capture()); + + assertNotNull(captor.getValue()); + } + + @Test + public void markdown() { + + final String input = "Hello ~~strike~~ and ~~through~~"; + + final Markwon markwon = Markwon.builder(RuntimeEnvironment.application) + .usePlugin(CorePlugin.create()) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { + builder.setFactory(Strikethrough.class, new SpanFactory() { + @Override + public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) { + return span("strikethrough"); + } + }); + } + }) + .build(); + + final TestSpan.Document document = document( + text("Hello "), + span("strikethrough", text("strike")), + text(" and "), + span("strikethrough", text("through")) + ); + + TestSpanMatcher.matches(markwon.toMarkdown(input), document); + } +} \ No newline at end of file diff --git a/markwon/build.gradle b/markwon/build.gradle index 8682d261..0f6f15db 100644 --- a/markwon/build.gradle +++ b/markwon/build.gradle @@ -28,7 +28,6 @@ dependencies { testImplementation it['robolectric'] testImplementation it['mockito'] - testImplementation it['ix-java'] testImplementation it['commons-io'] } } diff --git a/markwon/src/main/java/ru/noties/markwon/core/MarkwonTheme.java b/markwon/src/main/java/ru/noties/markwon/core/MarkwonTheme.java index 030c0a29..fc97875a 100644 --- a/markwon/src/main/java/ru/noties/markwon/core/MarkwonTheme.java +++ b/markwon/src/main/java/ru/noties/markwon/core/MarkwonTheme.java @@ -75,6 +75,7 @@ public class MarkwonTheme { * * @since 3.0.0 */ + @SuppressWarnings("unused") @NonNull public static Builder emptyBuilder() { return new Builder(); @@ -519,7 +520,7 @@ public class MarkwonTheme { return this; } - @SuppressWarnings("SameParameterValue") + @SuppressWarnings({"SameParameterValue", "UnusedReturnValue"}) @NonNull public Builder codeBackgroundColor(@ColorInt int codeBackgroundColor) { this.codeBackgroundColor = codeBackgroundColor;