Add fallbackToRawInputWhenEmpty configuration
This commit is contained in:
parent
c450765ab4
commit
d42ae41409
@ -10,10 +10,12 @@
|
|||||||
* Update `jlatexmath-android` dependency ([#225])
|
* Update `jlatexmath-android` dependency ([#225])
|
||||||
* Update `image-coil` module (Coil version `0.10.1`) ([#244])<br>Thanks to [@tylerbwong]
|
* 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)
|
* 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
|
[#235]: https://github.com/noties/Markwon/issues/235
|
||||||
[#225]: https://github.com/noties/Markwon/issues/225
|
[#225]: https://github.com/noties/Markwon/issues/225
|
||||||
[#244]: https://github.com/noties/Markwon/pull/244
|
[#244]: https://github.com/noties/Markwon/pull/244
|
||||||
|
[#242]: https://github.com/noties/Markwon/issues/242
|
||||||
[@tylerbwong]: https://github.com/tylerbwong
|
[@tylerbwong]: https://github.com/tylerbwong
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,6 +192,17 @@ public abstract class Markwon {
|
|||||||
@NonNull
|
@NonNull
|
||||||
Builder usePlugins(@NonNull Iterable<? extends MarkwonPlugin> plugins);
|
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
|
@NonNull
|
||||||
Markwon build();
|
Markwon build();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
|
|
||||||
private Markwon.TextSetter textSetter;
|
private Markwon.TextSetter textSetter;
|
||||||
|
|
||||||
|
// @since $nap;
|
||||||
|
private boolean fallbackToRawInputWhenEmpty = true;
|
||||||
|
|
||||||
MarkwonBuilderImpl(@NonNull Context context) {
|
MarkwonBuilderImpl(@NonNull Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@ -71,6 +74,13 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Markwon.Builder fallbackToRawInputWhenEmpty(boolean fallbackToRawInputWhenEmpty) {
|
||||||
|
this.fallbackToRawInputWhenEmpty = fallbackToRawInputWhenEmpty;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Markwon build() {
|
public Markwon build() {
|
||||||
@ -114,7 +124,8 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
parserBuilder.build(),
|
parserBuilder.build(),
|
||||||
visitorFactory,
|
visitorFactory,
|
||||||
configuration,
|
configuration,
|
||||||
Collections.unmodifiableList(plugins)
|
Collections.unmodifiableList(plugins),
|
||||||
|
fallbackToRawInputWhenEmpty
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package io.noties.markwon;
|
package io.noties.markwon;
|
||||||
|
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -28,19 +30,25 @@ class MarkwonImpl extends Markwon {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final TextSetter textSetter;
|
private final TextSetter textSetter;
|
||||||
|
|
||||||
|
// @since $nap;
|
||||||
|
private final boolean fallbackToRawInputWhenEmpty;
|
||||||
|
|
||||||
MarkwonImpl(
|
MarkwonImpl(
|
||||||
@NonNull TextView.BufferType bufferType,
|
@NonNull TextView.BufferType bufferType,
|
||||||
@Nullable TextSetter textSetter,
|
@Nullable TextSetter textSetter,
|
||||||
@NonNull Parser parser,
|
@NonNull Parser parser,
|
||||||
@NonNull MarkwonVisitorFactory visitorFactory,
|
@NonNull MarkwonVisitorFactory visitorFactory,
|
||||||
@NonNull MarkwonConfiguration configuration,
|
@NonNull MarkwonConfiguration configuration,
|
||||||
@NonNull List<MarkwonPlugin> plugins) {
|
@NonNull List<MarkwonPlugin> plugins,
|
||||||
|
boolean fallbackToRawInputWhenEmpty
|
||||||
|
) {
|
||||||
this.bufferType = bufferType;
|
this.bufferType = bufferType;
|
||||||
this.textSetter = textSetter;
|
this.textSetter = textSetter;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.visitorFactory = visitorFactory;
|
this.visitorFactory = visitorFactory;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.plugins = plugins;
|
this.plugins = plugins;
|
||||||
|
this.fallbackToRawInputWhenEmpty = fallbackToRawInputWhenEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -86,7 +94,18 @@ class MarkwonImpl extends Markwon {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Spanned toMarkdown(@NonNull String input) {
|
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
|
@Override
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.noties.markwon;
|
package io.noties.markwon;
|
||||||
|
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.commonmark.node.Node;
|
import org.commonmark.node.Node;
|
||||||
@ -50,7 +51,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.singletonList(plugin));
|
Collections.singletonList(plugin),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
impl.parse("whatever");
|
impl.parse("whatever");
|
||||||
|
|
||||||
@ -74,7 +77,9 @@ public class MarkwonImplTest {
|
|||||||
parser,
|
parser,
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Arrays.asList(first, second));
|
Arrays.asList(first, second),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
impl.parse("zero");
|
impl.parse("zero");
|
||||||
|
|
||||||
@ -102,7 +107,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
visitorFactory,
|
visitorFactory,
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.singletonList(plugin));
|
Collections.singletonList(plugin),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
when(visitorFactory.create()).thenReturn(visitor);
|
when(visitorFactory.create()).thenReturn(visitor);
|
||||||
when(visitor.builder()).thenReturn(builder);
|
when(visitor.builder()).thenReturn(builder);
|
||||||
@ -149,7 +156,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
visitorFactory,
|
visitorFactory,
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.<MarkwonPlugin>emptyList());
|
Collections.<MarkwonPlugin>emptyList(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
impl.render(mock(Node.class));
|
impl.render(mock(Node.class));
|
||||||
|
|
||||||
@ -185,7 +194,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
visitorFactory,
|
visitorFactory,
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.singletonList(plugin));
|
Collections.singletonList(plugin),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||||
final Node node = mock(Node.class);
|
final Node node = mock(Node.class);
|
||||||
@ -224,7 +235,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class, RETURNS_MOCKS),
|
mock(MarkwonVisitorFactory.class, RETURNS_MOCKS),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.singletonList(plugin));
|
Collections.singletonList(plugin),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
final TextView textView = mock(TextView.class);
|
final TextView textView = mock(TextView.class);
|
||||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||||
@ -272,7 +285,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
plugins);
|
plugins,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
assertTrue("First", impl.hasPlugin(First.class));
|
assertTrue("First", impl.hasPlugin(First.class));
|
||||||
assertFalse("Second", impl.hasPlugin(Second.class));
|
assertFalse("Second", impl.hasPlugin(Second.class));
|
||||||
@ -295,7 +310,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
Collections.singletonList(plugin));
|
Collections.singletonList(plugin),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
final TextView textView = mock(TextView.class);
|
final TextView textView = mock(TextView.class);
|
||||||
final Spanned spanned = mock(Spanned.class);
|
final Spanned spanned = mock(Spanned.class);
|
||||||
@ -339,7 +356,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
plugins);
|
plugins,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// should be returned
|
// should be returned
|
||||||
assertNotNull(impl.requirePlugin(MarkwonPlugin.class));
|
assertNotNull(impl.requirePlugin(MarkwonPlugin.class));
|
||||||
@ -370,7 +389,9 @@ public class MarkwonImplTest {
|
|||||||
mock(Parser.class),
|
mock(Parser.class),
|
||||||
mock(MarkwonVisitorFactory.class),
|
mock(MarkwonVisitorFactory.class),
|
||||||
mock(MarkwonConfiguration.class),
|
mock(MarkwonConfiguration.class),
|
||||||
plugins);
|
plugins,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
final List<? extends MarkwonPlugin> list = impl.getPlugins();
|
final List<? extends MarkwonPlugin> list = impl.getPlugins();
|
||||||
|
|
||||||
@ -385,4 +406,42 @@ public class MarkwonImplTest {
|
|||||||
assertTrue(e.getMessage(), true);
|
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