Add fallbackToRawInputWhenEmpty configuration
This commit is contained in:
parent
c450765ab4
commit
d42ae41409
@ -10,10 +10,12 @@
|
||||
* Update `jlatexmath-android` dependency ([#225])
|
||||
* Update `image-coil` module (Coil version `0.10.1`) ([#244])<br>Thanks to [@tylerbwong]
|
||||
* Rename `UrlProcessor` to `ImageDestinationProcessor` (`io.noties.markwon.urlprocessor` -> `io.noties.markwon.image.destination`) and limit its usage to process **only** destination URL of images (was used to also process links before)
|
||||
* `fallbackToRawInputWhenEmpty` `Markwon.Builder` configuration to fallback to raw input if rendered markdown is empty ([#242])
|
||||
|
||||
[#235]: https://github.com/noties/Markwon/issues/235
|
||||
[#225]: https://github.com/noties/Markwon/issues/225
|
||||
[#244]: https://github.com/noties/Markwon/pull/244
|
||||
[#242]: https://github.com/noties/Markwon/issues/242
|
||||
[@tylerbwong]: https://github.com/tylerbwong
|
||||
|
||||
|
||||
|
@ -192,6 +192,17 @@ public abstract class Markwon {
|
||||
@NonNull
|
||||
Builder usePlugins(@NonNull Iterable<? extends MarkwonPlugin> plugins);
|
||||
|
||||
/**
|
||||
* Control if small chunks of non-finished markdown sentences (for example, a single `*` character)
|
||||
* should be displayed/rendered as raw input instead of an empty string.
|
||||
* <p>
|
||||
* Since $nap; {@code true} by default, versions prior - {@code false}
|
||||
*
|
||||
* @since $nap;
|
||||
*/
|
||||
@NonNull
|
||||
Builder fallbackToRawInputWhenEmpty(boolean fallbackToRawInputWhenEmpty);
|
||||
|
||||
@NonNull
|
||||
Markwon build();
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
||||
|
||||
private Markwon.TextSetter textSetter;
|
||||
|
||||
// @since $nap;
|
||||
private boolean fallbackToRawInputWhenEmpty = true;
|
||||
|
||||
MarkwonBuilderImpl(@NonNull Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
@ -71,6 +74,13 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Markwon.Builder fallbackToRawInputWhenEmpty(boolean fallbackToRawInputWhenEmpty) {
|
||||
this.fallbackToRawInputWhenEmpty = fallbackToRawInputWhenEmpty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Markwon build() {
|
||||
@ -114,7 +124,8 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
||||
parserBuilder.build(),
|
||||
visitorFactory,
|
||||
configuration,
|
||||
Collections.unmodifiableList(plugins)
|
||||
Collections.unmodifiableList(plugins),
|
||||
fallbackToRawInputWhenEmpty
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package io.noties.markwon;
|
||||
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -28,19 +30,25 @@ class MarkwonImpl extends Markwon {
|
||||
@Nullable
|
||||
private final TextSetter textSetter;
|
||||
|
||||
// @since $nap;
|
||||
private final boolean fallbackToRawInputWhenEmpty;
|
||||
|
||||
MarkwonImpl(
|
||||
@NonNull TextView.BufferType bufferType,
|
||||
@Nullable TextSetter textSetter,
|
||||
@NonNull Parser parser,
|
||||
@NonNull MarkwonVisitorFactory visitorFactory,
|
||||
@NonNull MarkwonConfiguration configuration,
|
||||
@NonNull List<MarkwonPlugin> plugins) {
|
||||
@NonNull List<MarkwonPlugin> plugins,
|
||||
boolean fallbackToRawInputWhenEmpty
|
||||
) {
|
||||
this.bufferType = bufferType;
|
||||
this.textSetter = textSetter;
|
||||
this.parser = parser;
|
||||
this.visitorFactory = visitorFactory;
|
||||
this.configuration = configuration;
|
||||
this.plugins = plugins;
|
||||
this.fallbackToRawInputWhenEmpty = fallbackToRawInputWhenEmpty;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -86,7 +94,18 @@ class MarkwonImpl extends Markwon {
|
||||
@NonNull
|
||||
@Override
|
||||
public Spanned toMarkdown(@NonNull String input) {
|
||||
return render(parse(input));
|
||||
final Spanned spanned = render(parse(input));
|
||||
|
||||
// @since $nap;
|
||||
// if spanned is empty, we are configured to use raw input and input is not empty
|
||||
if (TextUtils.isEmpty(spanned)
|
||||
&& fallbackToRawInputWhenEmpty
|
||||
&& !TextUtils.isEmpty(input)) {
|
||||
// let's use SpannableStringBuilder in order to keep backward-compatibility
|
||||
return new SpannableStringBuilder(input);
|
||||
}
|
||||
|
||||
return spanned;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.noties.markwon;
|
||||
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
@ -50,7 +51,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.singletonList(plugin));
|
||||
Collections.singletonList(plugin),
|
||||
true
|
||||
);
|
||||
|
||||
impl.parse("whatever");
|
||||
|
||||
@ -74,7 +77,9 @@ public class MarkwonImplTest {
|
||||
parser,
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Arrays.asList(first, second));
|
||||
Arrays.asList(first, second),
|
||||
true
|
||||
);
|
||||
|
||||
impl.parse("zero");
|
||||
|
||||
@ -102,7 +107,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
visitorFactory,
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.singletonList(plugin));
|
||||
Collections.singletonList(plugin),
|
||||
true
|
||||
);
|
||||
|
||||
when(visitorFactory.create()).thenReturn(visitor);
|
||||
when(visitor.builder()).thenReturn(builder);
|
||||
@ -149,7 +156,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
visitorFactory,
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.<MarkwonPlugin>emptyList());
|
||||
Collections.<MarkwonPlugin>emptyList(),
|
||||
true
|
||||
);
|
||||
|
||||
impl.render(mock(Node.class));
|
||||
|
||||
@ -185,7 +194,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
visitorFactory,
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.singletonList(plugin));
|
||||
Collections.singletonList(plugin),
|
||||
true
|
||||
);
|
||||
|
||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||
final Node node = mock(Node.class);
|
||||
@ -224,7 +235,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class, RETURNS_MOCKS),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.singletonList(plugin));
|
||||
Collections.singletonList(plugin),
|
||||
true
|
||||
);
|
||||
|
||||
final TextView textView = mock(TextView.class);
|
||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||
@ -272,7 +285,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
plugins);
|
||||
plugins,
|
||||
true
|
||||
);
|
||||
|
||||
assertTrue("First", impl.hasPlugin(First.class));
|
||||
assertFalse("Second", impl.hasPlugin(Second.class));
|
||||
@ -295,7 +310,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.singletonList(plugin));
|
||||
Collections.singletonList(plugin),
|
||||
true
|
||||
);
|
||||
|
||||
final TextView textView = mock(TextView.class);
|
||||
final Spanned spanned = mock(Spanned.class);
|
||||
@ -339,7 +356,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
plugins);
|
||||
plugins,
|
||||
true
|
||||
);
|
||||
|
||||
// should be returned
|
||||
assertNotNull(impl.requirePlugin(MarkwonPlugin.class));
|
||||
@ -370,7 +389,9 @@ public class MarkwonImplTest {
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitorFactory.class),
|
||||
mock(MarkwonConfiguration.class),
|
||||
plugins);
|
||||
plugins,
|
||||
true
|
||||
);
|
||||
|
||||
final List<? extends MarkwonPlugin> list = impl.getPlugins();
|
||||
|
||||
@ -385,4 +406,42 @@ public class MarkwonImplTest {
|
||||
assertTrue(e.getMessage(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fallback_to_raw() {
|
||||
final String md = "*";
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
null,
|
||||
mock(Parser.class, RETURNS_MOCKS),
|
||||
// it must be sufficient to just return mocks and thus empty rendering result
|
||||
mock(MarkwonVisitorFactory.class, RETURNS_MOCKS),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.<MarkwonPlugin>emptyList(),
|
||||
true
|
||||
);
|
||||
|
||||
final Spanned spanned = impl.toMarkdown(md);
|
||||
assertEquals(md, spanned.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fallback_to_raw_false() {
|
||||
final String md = "*";
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
null,
|
||||
mock(Parser.class, RETURNS_MOCKS),
|
||||
// it must be sufficient to just return mocks and thus empty rendering result
|
||||
mock(MarkwonVisitorFactory.class, RETURNS_MOCKS),
|
||||
mock(MarkwonConfiguration.class),
|
||||
Collections.<MarkwonPlugin>emptyList(),
|
||||
false
|
||||
);
|
||||
|
||||
final Spanned spanned = impl.toMarkdown(md);
|
||||
assertTrue(spanned.toString(), TextUtils.isEmpty(spanned));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user