Add tests for markwon-image module
This commit is contained in:
		
							parent
							
								
									cedb3971a0
								
							
						
					
					
						commit
						6bf04e38ad
					
				| @ -165,14 +165,17 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Text text) { | ||||
| 
 | ||||
|                 final int length = visitor.length(); | ||||
|                 final String literal = text.getLiteral(); | ||||
| 
 | ||||
|                 visitor.builder().append(literal); | ||||
| 
 | ||||
|                 // @since 4.0.0-SNAPSHOT | ||||
|                 for (OnTextAddedListener onTextAddedListener : onTextAddedListeners) { | ||||
|                     onTextAddedListener.onTextAdded(visitor, literal, length); | ||||
|                 if (!onTextAddedListeners.isEmpty()) { | ||||
|                     // calculate the start position | ||||
|                     final int length = visitor.length() - literal.length(); | ||||
|                     for (OnTextAddedListener onTextAddedListener : onTextAddedListeners) { | ||||
|                         onTextAddedListener.onTextAdded(visitor, literal, length); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|  | ||||
| @ -27,6 +27,4 @@ public abstract class AsyncDrawableLoader { | ||||
|     @Nullable | ||||
|     public abstract Drawable placeholder(@NonNull AsyncDrawable drawable); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -4,7 +4,7 @@ import android.graphics.drawable.Drawable; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| 
 | ||||
| public class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader { | ||||
| class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader { | ||||
|     @Override | ||||
|     public void load(@NonNull AsyncDrawable drawable) { | ||||
| 
 | ||||
|  | ||||
| @ -93,6 +93,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     private final JLatextAsyncDrawableLoader jLatextAsyncDrawableLoader; | ||||
| 
 | ||||
|     @SuppressWarnings("WeakerAccess") | ||||
|     JLatexMathPlugin(@NonNull Config config) { | ||||
|         this.jLatextAsyncDrawableLoader = new JLatextAsyncDrawableLoader(config); | ||||
|     } | ||||
|  | ||||
| @ -8,6 +8,9 @@ import java.util.Map; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Executors; | ||||
| 
 | ||||
| import ru.noties.markwon.image.data.DataUriSchemeHandler; | ||||
| import ru.noties.markwon.image.network.NetworkSchemeHandler; | ||||
| 
 | ||||
| class AsyncDrawableLoaderBuilder { | ||||
| 
 | ||||
|     ExecutorService executorService; | ||||
| @ -19,6 +22,15 @@ class AsyncDrawableLoaderBuilder { | ||||
| 
 | ||||
|     boolean isBuilt; | ||||
| 
 | ||||
|     AsyncDrawableLoaderBuilder() { | ||||
| 
 | ||||
|         // @since 4.0.0-SNAPSHOT | ||||
|         // okay, let's add supported schemes at the start, this would be : data-uri and default network | ||||
|         // we should not use file-scheme as it's a bit complicated to assume file usage (lack of permissions) | ||||
|         addSchemeHandler(DataUriSchemeHandler.create()); | ||||
|         addSchemeHandler(NetworkSchemeHandler.create()); | ||||
|     } | ||||
| 
 | ||||
|     void executorService(@NonNull ExecutorService executorService) { | ||||
|         this.executorService = executorService; | ||||
|     } | ||||
| @ -66,12 +78,6 @@ class AsyncDrawableLoaderBuilder { | ||||
| 
 | ||||
|         isBuilt = true; | ||||
| 
 | ||||
|         // we must have schemeHandlers registered (we will provide | ||||
|         // default media decoder if it's absent) | ||||
|         if (schemeHandlers.size() == 0) { | ||||
|             return new AsyncDrawableLoaderNoOp(); | ||||
|         } | ||||
| 
 | ||||
|         // @since 4.0.0-SNAPSHOT | ||||
|         if (defaultMediaDecoder == null) { | ||||
|             defaultMediaDecoder = DefaultImageMediaDecoder.create(); | ||||
| @ -83,5 +89,4 @@ class AsyncDrawableLoaderBuilder { | ||||
| 
 | ||||
|         return new AsyncDrawableLoaderImpl(this); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -14,6 +14,7 @@ import ru.noties.markwon.AbstractMarkwonPlugin; | ||||
| import ru.noties.markwon.MarkwonConfiguration; | ||||
| import ru.noties.markwon.MarkwonSpansFactory; | ||||
| 
 | ||||
| @SuppressWarnings({"UnusedReturnValue", "WeakerAccess"}) | ||||
| public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     /** | ||||
| @ -91,6 +92,12 @@ public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @see DefaultImageMediaDecoder | ||||
|      * @see ru.noties.markwon.image.svg.SvgMediaDecoder | ||||
|      * @see ru.noties.markwon.image.gif.GifMediaDecoder | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin addMediaDecoder(@NonNull MediaDecoder mediaDecoder) { | ||||
|         checkBuilderState(); | ||||
| @ -98,13 +105,23 @@ public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Please note that if not specified a {@link DefaultImageMediaDecoder} will be used. So | ||||
|      * if you need to disable default-image-media-decoder specify here own no-op implementation. | ||||
|      * | ||||
|      * @see DefaultImageMediaDecoder | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) { | ||||
|     public ImagesPlugin defaultMediaDecoder(@NonNull MediaDecoder mediaDecoder) { | ||||
|         checkBuilderState(); | ||||
|         builder.defaultMediaDecoder(mediaDecoder); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin removeSchemeHandler(@NonNull String scheme) { | ||||
|         checkBuilderState(); | ||||
| @ -112,6 +129,9 @@ public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin removeMediaDecoder(@NonNull String contentType) { | ||||
|         checkBuilderState(); | ||||
| @ -119,6 +139,9 @@ public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin placeholderProvider(@NonNull PlaceholderProvider placeholderProvider) { | ||||
|         checkBuilderState(); | ||||
| @ -126,6 +149,10 @@ public class ImagesPlugin extends AbstractMarkwonPlugin { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @see ErrorHandler | ||||
|      * @since 4.0.0-SNAPSHOT | ||||
|      */ | ||||
|     @NonNull | ||||
|     public ImagesPlugin errorHandler(@NonNull ErrorHandler errorHandler) { | ||||
|         checkBuilderState(); | ||||
|  | ||||
| @ -0,0 +1,194 @@ | ||||
| package ru.noties.markwon.image; | ||||
| 
 | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.robolectric.RobolectricTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| 
 | ||||
| import ru.noties.markwon.image.data.DataUriSchemeHandler; | ||||
| import ru.noties.markwon.image.network.NetworkSchemeHandler; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertFalse; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.when; | ||||
| 
 | ||||
| @RunWith(RobolectricTestRunner.class) | ||||
| @Config(manifest = Config.NONE) | ||||
| public class AsyncDrawableLoaderBuilderTest { | ||||
| 
 | ||||
|     private AsyncDrawableLoaderBuilder builder; | ||||
| 
 | ||||
|     @Before | ||||
|     public void before() { | ||||
|         builder = new AsyncDrawableLoaderBuilder(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void default_scheme_handlers() { | ||||
|         // builder adds default data-uri and network scheme-handlers | ||||
| 
 | ||||
|         final String[] registered = { | ||||
|                 DataUriSchemeHandler.SCHEME, | ||||
|                 NetworkSchemeHandler.SCHEME_HTTP, | ||||
|                 NetworkSchemeHandler.SCHEME_HTTPS | ||||
|         }; | ||||
| 
 | ||||
|         for (String scheme : registered) { | ||||
|             assertNotNull(scheme, builder.schemeHandlers.get(scheme)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void built_flag() { | ||||
|         // isBuilt flag must be set after `build` method call | ||||
| 
 | ||||
|         assertFalse(builder.isBuilt); | ||||
| 
 | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertTrue(builder.isBuilt); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void defaults_initialized() { | ||||
|         // default-media-decoder and executor-service must be initialized | ||||
| 
 | ||||
|         assertNull(builder.defaultMediaDecoder); | ||||
|         assertNull(builder.executorService); | ||||
| 
 | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertNotNull(builder.defaultMediaDecoder); | ||||
|         assertNotNull(builder.executorService); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void executor() { | ||||
|         // supplied executor-service must be used | ||||
| 
 | ||||
|         assertNull(builder.executorService); | ||||
| 
 | ||||
|         final ExecutorService service = mock(ExecutorService.class); | ||||
|         builder.executorService(service); | ||||
| 
 | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertEquals(service, builder.executorService); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void add_scheme_handler() { | ||||
| 
 | ||||
|         final String scheme = "mock"; | ||||
|         assertNull(builder.schemeHandlers.get(scheme)); | ||||
| 
 | ||||
|         final SchemeHandler schemeHandler = mock(SchemeHandler.class); | ||||
|         when(schemeHandler.supportedSchemes()).thenReturn(Collections.singleton(scheme)); | ||||
| 
 | ||||
|         builder.addSchemeHandler(schemeHandler); | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertEquals(schemeHandler, builder.schemeHandlers.get(scheme)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void add_scheme_handler_multiple_types() { | ||||
|         // all supported types are registered | ||||
| 
 | ||||
|         final String[] schemes = { | ||||
|                 "mock-1", | ||||
|                 "mock-2" | ||||
|         }; | ||||
| 
 | ||||
|         final SchemeHandler schemeHandler = mock(SchemeHandler.class); | ||||
|         when(schemeHandler.supportedSchemes()).thenReturn(Arrays.asList(schemes)); | ||||
| 
 | ||||
|         builder.addSchemeHandler(schemeHandler); | ||||
| 
 | ||||
|         for (String scheme : schemes) { | ||||
|             assertEquals(scheme, schemeHandler, builder.schemeHandlers.get(scheme)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void add_media_decoder() { | ||||
| 
 | ||||
|         final String media = "mocked/type"; | ||||
|         assertNull(builder.mediaDecoders.get(media)); | ||||
| 
 | ||||
|         final MediaDecoder mediaDecoder = mock(MediaDecoder.class); | ||||
|         when(mediaDecoder.supportedTypes()).thenReturn(Collections.singleton(media)); | ||||
| 
 | ||||
|         builder.addMediaDecoder(mediaDecoder); | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertEquals(mediaDecoder, builder.mediaDecoders.get(media)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void add_media_decoder_multiple_types() { | ||||
| 
 | ||||
|         final String[] types = { | ||||
|                 "mock/type1", | ||||
|                 "mock/type2" | ||||
|         }; | ||||
| 
 | ||||
|         final MediaDecoder mediaDecoder = mock(MediaDecoder.class); | ||||
|         when(mediaDecoder.supportedTypes()).thenReturn(Arrays.asList(types)); | ||||
| 
 | ||||
|         builder.addMediaDecoder(mediaDecoder); | ||||
| 
 | ||||
|         for (String type : types) { | ||||
|             assertEquals(type, mediaDecoder, builder.mediaDecoders.get(type)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void default_media_decoder() { | ||||
| 
 | ||||
|         assertNull(builder.defaultMediaDecoder); | ||||
| 
 | ||||
|         final MediaDecoder mediaDecoder = mock(MediaDecoder.class); | ||||
|         builder.defaultMediaDecoder(mediaDecoder); | ||||
|         builder.build(); | ||||
| 
 | ||||
|         assertEquals(mediaDecoder, builder.defaultMediaDecoder); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void remove_scheme_handler() { | ||||
| 
 | ||||
|         final String scheme = "mock"; | ||||
|         final SchemeHandler schemeHandler = mock(SchemeHandler.class); | ||||
|         when(schemeHandler.supportedSchemes()).thenReturn(Collections.singleton(scheme)); | ||||
| 
 | ||||
|         assertNull(builder.schemeHandlers.get(scheme)); | ||||
|         builder.addSchemeHandler(schemeHandler); | ||||
|         assertNotNull(builder.schemeHandlers.get(scheme)); | ||||
|         builder.removeSchemeHandler(scheme); | ||||
|         assertNull(builder.schemeHandlers.get(scheme)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void remove_media_decoder() { | ||||
| 
 | ||||
|         final String media = "mock/type"; | ||||
|         final MediaDecoder mediaDecoder = mock(MediaDecoder.class); | ||||
|         when(mediaDecoder.supportedTypes()).thenReturn(Collections.singleton(media)); | ||||
| 
 | ||||
|         assertNull(builder.mediaDecoders.get(media)); | ||||
|         builder.addMediaDecoder(mediaDecoder); | ||||
|         assertNotNull(builder.mediaDecoders.get(media)); | ||||
|         builder.removeMediaDecoder(media); | ||||
|         assertNull(builder.mediaDecoders.get(media)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,177 @@ | ||||
| package ru.noties.markwon.image; | ||||
| 
 | ||||
| import android.support.annotation.NonNull; | ||||
| import android.text.Spanned; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import org.commonmark.node.Image; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.mockito.ArgumentCaptor; | ||||
| import org.robolectric.RobolectricTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| 
 | ||||
| import java.util.concurrent.ExecutorService; | ||||
| 
 | ||||
| import ru.noties.markwon.MarkwonConfiguration; | ||||
| import ru.noties.markwon.MarkwonSpansFactory; | ||||
| import ru.noties.markwon.SpanFactory; | ||||
| import ru.noties.markwon.image.data.DataUriSchemeHandler; | ||||
| 
 | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.junit.Assert.fail; | ||||
| 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 org.mockito.Mockito.when; | ||||
| 
 | ||||
| @RunWith(RobolectricTestRunner.class) | ||||
| @Config(manifest = Config.NONE) | ||||
| public class ImagesPluginTest { | ||||
| 
 | ||||
|     private ImagesPlugin plugin; | ||||
| 
 | ||||
|     @Before | ||||
|     public void before() { | ||||
|         plugin = ImagesPlugin.create(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void build_state() { | ||||
|         // it's not possible to mutate images-plugin after `configureConfiguration` call | ||||
| 
 | ||||
|         // validate that it doesn't throw here | ||||
|         plugin.addSchemeHandler(DataUriSchemeHandler.create()); | ||||
| 
 | ||||
|         // mark the state | ||||
|         plugin.configureConfiguration(mock(MarkwonConfiguration.Builder.class)); | ||||
| 
 | ||||
|         final class Throws { | ||||
|             private void assertThrows(@NonNull Runnable action) { | ||||
|                 //noinspection CatchMayIgnoreException | ||||
|                 try { | ||||
|                     action.run(); | ||||
|                     fail(); | ||||
|                 } catch (Throwable t) { | ||||
|                     assertTrue(t.getMessage(), t.getMessage().contains("ImagesPlugin has already been configured")); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         final Throws check = new Throws(); | ||||
| 
 | ||||
|         // executor-service | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.executorService(mock(ExecutorService.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // add-scheme-handler | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.addSchemeHandler(mock(SchemeHandler.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // add-media-decoder | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.addMediaDecoder(mock(MediaDecoder.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // default-media-decoder | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.defaultMediaDecoder(mock(MediaDecoder.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // remove-scheme-handler | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.removeSchemeHandler("mock"); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // remove-media-decoder | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.removeMediaDecoder("mock/type"); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // placeholder-provider | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.placeholderProvider(mock(ImagesPlugin.PlaceholderProvider.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // error-handler | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.errorHandler(mock(ImagesPlugin.ErrorHandler.class)); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // final check if for actual `configureConfiguration` call (must be called only once) | ||||
|         check.assertThrows(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 plugin.configureConfiguration(mock(MarkwonConfiguration.Builder.class)); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void image_span_factory_registered() { | ||||
| 
 | ||||
|         final MarkwonSpansFactory.Builder builder = mock(MarkwonSpansFactory.Builder.class); | ||||
| 
 | ||||
|         plugin.configureSpansFactory(builder); | ||||
| 
 | ||||
|         final ArgumentCaptor<SpanFactory> captor = ArgumentCaptor.forClass(SpanFactory.class); | ||||
| 
 | ||||
|         verify(builder, times(1)) | ||||
|                 .setFactory(eq(Image.class), captor.capture()); | ||||
| 
 | ||||
|         assertNotNull(captor.getValue()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void before_set_text() { | ||||
|         // verify that AsyncDrawableScheduler is called | ||||
| 
 | ||||
|         final TextView textView = mock(TextView.class); | ||||
| 
 | ||||
|         plugin.beforeSetText(textView, mock(Spanned.class)); | ||||
| 
 | ||||
|         verify(textView, times(1)) | ||||
|                 .getTag(eq(R.id.markwon_drawables_scheduler_last_text_hashcode)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void after_set_text() { | ||||
|         // verify that AsyncDrawableScheduler is called | ||||
| 
 | ||||
|         final TextView textView = mock(TextView.class); | ||||
|         when(textView.getText()).thenReturn("some text"); | ||||
| 
 | ||||
|         plugin.afterSetText(textView); | ||||
| 
 | ||||
|         verify(textView, times(1)) | ||||
|                 .getTag(eq(R.id.markwon_drawables_scheduler_last_text_hashcode)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										5
									
								
								markwon-linkify/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								markwon-linkify/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| # Linkify | ||||
| 
 | ||||
| Use this module (or take a hint from it) if you would need _linkify_ capabilities. Do not | ||||
| use `TextView.setAutolinkMask` (or specify `autolink` in XML) because it will remove all  | ||||
| existing links and keep only the ones it creates. | ||||
| @ -18,8 +18,7 @@ public class LinkifyPlugin extends AbstractMarkwonPlugin { | ||||
|     @IntDef(flag = true, value = { | ||||
|             Linkify.EMAIL_ADDRESSES, | ||||
|             Linkify.PHONE_NUMBERS, | ||||
|             Linkify.WEB_URLS, | ||||
|             Linkify.ALL | ||||
|             Linkify.WEB_URLS | ||||
|     }) | ||||
|     @Retention(RetentionPolicy.SOURCE) | ||||
|     @interface LinkifyMask { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov