Working with documentation
This commit is contained in:
		
							parent
							
								
									d91f367e0a
								
							
						
					
					
						commit
						18fd56a97c
					
				| @ -49,17 +49,20 @@ module.exports = { | ||||
|                         '/docs/core/configuration.md', | ||||
|                         '/docs/core/visitor.md', | ||||
|                         '/docs/core/spans-factory.md', | ||||
|                         '/docs/core/html-renderer.md' | ||||
|                         '/docs/core/html-renderer.md', | ||||
|                         '/docs/core/core-plugin.md', | ||||
|                         '/docs/core/movement-method-plugin.md' | ||||
|                     ] | ||||
|                 }, | ||||
|                 '/docs/ext-latex/', | ||||
|                 '/docs/ext-strikethrough/strikethrough.md', | ||||
|                 '/docs/ext-tables/tables.md', | ||||
|                 '/docs/ext-tasklist/tasklist.md', | ||||
|                 '/docs/ext-strikethrough/', | ||||
|                 '/docs/ext-tables/', | ||||
|                 '/docs/ext-tasklist/', | ||||
|                 { | ||||
|                     title: 'HTML', | ||||
|                     children: [ | ||||
|                         '/docs/html/html.md' | ||||
|                         '/docs/html/', | ||||
|                         '/docs/html/custom-tag-handler.md' | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
| @ -70,8 +73,8 @@ module.exports = { | ||||
|                         '/docs/image/svg.md' | ||||
|                     ] | ||||
|                 }, | ||||
|                 '/docs/recycler/recycler.md', | ||||
|                 '/docs/syntax-highlight/syntax-highlight.md', | ||||
|                 '/docs/recycler/', | ||||
|                 '/docs/syntax-highlight/', | ||||
|                 '/docs/migration-2-3.md' | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
| @ -25,18 +25,19 @@ listed in <Link name="commonmark-spec" /> are supported (including support for * | ||||
| 
 | ||||
| * Emphasis (`*`, `_`) | ||||
| * Strong emphasis (`**`, `__`) | ||||
| * Strike-through (`~~`) | ||||
| * Headers (`#{1,6}`) | ||||
| * Links (`[]()` && `[][]`) | ||||
| * [Images](/docs/image-loader.md) | ||||
| * [Images](/docs/core/images.md) | ||||
| * Thematic break (`---`, `***`, `___`) | ||||
| * Quotes & nested quotes (`>{1,}`) | ||||
| * Ordered & non-ordered lists & nested ones | ||||
| * Inline code | ||||
| * Code blocks | ||||
| * Tables (*with limitations*) | ||||
| * [Syntax highlight](/docs/syntax-highlight.md) | ||||
| * [HTML](/docs/html.md) | ||||
| * [Strike-through](/docs/ext-strikethrough/) (`~~`) | ||||
| * [Tables](/docs/ext-tables/) (*with limitations*) | ||||
| * [Syntax highlight](/docs/syntax-highlight/) | ||||
| * [LaTeX](/docs/ext-latex/) formulas | ||||
| * [HTML](/docs/html/) | ||||
|   * Emphasis (`<i>`, `<em>`, `<cite>`, `<dfn>`) | ||||
|   * Strong emphasis (`<b>`, `<strong>`) | ||||
|   * SuperScript (`<sup>`) | ||||
| @ -49,8 +50,8 @@ listed in <Link name="commonmark-spec" /> are supported (including support for * | ||||
|   * Blockquote (`blockquote`) | ||||
|   * Heading (`h1`, `h2`, `h3`, `h4`, `h5`, `h6`) | ||||
|   * there is support to render any HTML tag, but it will require to create a special `TagHandler`, | ||||
|     more information can be found in [HTML section](/docs/html.md#custom-tag-handler) | ||||
| * Task lists: | ||||
|     more information can be found in [HTML section](/docs/html/custom-tag-handler.md) | ||||
| * [Task lists](/docs/ext-tasklist/): | ||||
| - [ ] Not _done_ | ||||
|   - [X] **Done** with `X` | ||||
|   - [x] ~~and~~ **or** small `x` | ||||
|  | ||||
							
								
								
									
										103
									
								
								docs/docs/core/core-plugin.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								docs/docs/core/core-plugin.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| # Core plugin <Badge text="3.0.0" /> | ||||
| 
 | ||||
| Since <Badge text="3.0.0" /> with introduction of _plugins_, Markwon | ||||
| **core** functionality was moved to a dedicated plugin. | ||||
| 
 | ||||
| ```java | ||||
| CorePlugin.create(); | ||||
| ``` | ||||
| 
 | ||||
| ## Node visitors | ||||
| 
 | ||||
| `CorePlugin` registers these `commonmark-java` node visitors: | ||||
| * `Text` | ||||
| * `StrongEmphasis` | ||||
| * `Emphasis` | ||||
| * `BlockQuote` | ||||
| * `Code` | ||||
| * `FencedCodeBlock` | ||||
| * `IndentedCodeBlock` | ||||
| * `BulletList` | ||||
| * `OrderedList` | ||||
| * `ListItem` | ||||
| * `ThematicBreak` | ||||
| * `Heading` | ||||
| * `SoftLineBreak` | ||||
| * `HardLineBreak` | ||||
| * `Paragraph` | ||||
| * `Link` | ||||
| 
 | ||||
| ## Span factories | ||||
| 
 | ||||
| `CorePlugin` adds these `SpanFactory`s: | ||||
| * `StrongEmphasis` | ||||
| * `Emphasis` | ||||
| * `BlockQuote` | ||||
| * `Code` | ||||
| * `FencedCodeBlock` | ||||
| * `IndentedCodeBlock` | ||||
| * `ListItem` | ||||
| * `Heading` | ||||
| * `Link` | ||||
| * `ThematicBreak` | ||||
| 
 | ||||
| 
 | ||||
| :::tip | ||||
| By default `CorePlugin` does not register a `Paragraph` `SpanFactory` but | ||||
| this can be done in your custom plugin: | ||||
| 
 | ||||
| ```java | ||||
| Markwon.builder(context) | ||||
|         .usePlugin(new AbstractMarkwonPlugin() { | ||||
|             @Override | ||||
|             public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { | ||||
|                 builder.setFactory(Paragraph.class, (configuration, props) ->  | ||||
|                         new ForegroundColorSpan(Color.RED)); | ||||
|             } | ||||
|         }) | ||||
| ``` | ||||
| ::: | ||||
| 
 | ||||
| ## Props | ||||
| These props are exported by `CorePlugin` and can be found in `CoreProps`: | ||||
| * `Prop<ListItemType> LIST_ITEM_TYPE` (BULLET | ORDERED) | ||||
| * `Prop<Integer> BULLET_LIST_ITEM_LEVEL` | ||||
| * `Prop<Integer> ORDERED_LIST_ITEM_NUMBER` | ||||
| * `Prop<Integer> HEADING_LEVEL` | ||||
| * `Prop<String> LINK_DESTINATION` | ||||
| * `Prop<Boolean> PARAGRAPH_IS_IN_TIGHT_LIST` | ||||
| 
 | ||||
| :::warning List item type | ||||
| Before <Badge text="3.0.0" /> `Markwon` had 2 distinct lists (bullet and ordered).  | ||||
| Since <Badge text="3.0.0" /> a single `SpanFactory` is used, which internally checks  | ||||
| for `Prop<ListItemType> LIST_ITEM_TYPE`. | ||||
| Beware of this if you would like to override only one of the list types. This is | ||||
| done to correspond to `commonmark-java` implementation. | ||||
| ::: | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| :::tip Soft line break | ||||
| Since <Badge text="3.0.0" /> Markwon core does not give an option to | ||||
| insert a new line when there is a soft line break in markdown. Instead a | ||||
| custom plugin can be used: | ||||
| 
 | ||||
| ```java | ||||
| final Markwon markwon = Markwon.builder(this) | ||||
|         .usePlugin(new AbstractMarkwonPlugin() { | ||||
|             @Override | ||||
|             public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { | ||||
|                 builder.on(SoftLineBreak.class, (visitor, softLineBreak) -> | ||||
|                         visitor.forceNewLine()); | ||||
|             } | ||||
|         }) | ||||
|         .build(); | ||||
| ``` | ||||
| ::: | ||||
| 
 | ||||
| :::warning | ||||
| Please note that `CorePlugin` will implicitly set a `LinkMovementMethod` on a TextView | ||||
| if one is not present. If you wish to customize a MovementMethod that is used, apply | ||||
| one manually to a TextView (before applying markdown) or use the [MovementMethodPlugin](/docs/core/movement-method-plugin.md) | ||||
| which accepts a MovementMethod as an argument. | ||||
| ::: | ||||
							
								
								
									
										17
									
								
								docs/docs/core/movement-method-plugin.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								docs/docs/core/movement-method-plugin.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| # Movement method plugin | ||||
| 
 | ||||
| `MovementMethodPlugin` can be used to apply a `MovementMethod` to a TextView | ||||
| (important if you have links inside your markdown). By default `CorePlugin` | ||||
| will set a `LinkMovementMethod` on a TextView if one is missing. If you have | ||||
| specific needs for a `MovementMethod` and `LinkMovementMethod` doesn't answer | ||||
| your needs use `MovementMethodPlugin`: | ||||
| 
 | ||||
| ```java | ||||
| Markwon.builder(context) | ||||
|         .usePlugin(MovementMethodPlugin.create(ScrollingMovementMethod.getInstance())) | ||||
| ``` | ||||
| 
 | ||||
| :::tip | ||||
| If you are having trouble with system `LinkMovementMethod` as an alternative | ||||
| [BetterLinkMovementMethod](https://github.com/saket/Better-Link-Movement-Method) library can be used. | ||||
| ::: | ||||
| @ -24,6 +24,19 @@ final Markwon markwon = Markwon.builder(context) | ||||
|         .usePlugin(TablePlugin.create(tableTheme)) | ||||
| ``` | ||||
| 
 | ||||
| ```java | ||||
| Markwon.builder(context) | ||||
|         .usePlugin(TablePlugin.create(builder -> | ||||
|                 builder | ||||
|                         .tableBorderColor(Color.RED) | ||||
|                         .tableBorderWidth(0) | ||||
|                         .tableCellPadding(0) | ||||
|                         .tableHeaderRowBackgroundColor(Color.BLACK) | ||||
|                         .tableEvenRowBackgroundColor(Color.GREEN) | ||||
|                         .tableOddRowBackgroundColor(Color.YELLOW) | ||||
| )) | ||||
| ``` | ||||
| 
 | ||||
| Please note, that _by default_ tables have limitations. For example, there is no support | ||||
| for images inside table cells. And table contents won't be copied to clipboard if a TextView | ||||
| has such functionality. Table will always take full width of a TextView in which it is displayed. | ||||
							
								
								
									
										1
									
								
								docs/docs/html/custom-tag-handler.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/docs/html/custom-tag-handler.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| # HTML custom tag handler | ||||
| @ -50,18 +50,10 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CorePlugin create() { | ||||
|         return create(false); | ||||
|         return new CorePlugin(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CorePlugin create(boolean softBreakAddsNewLine) { | ||||
|         return new CorePlugin(softBreakAddsNewLine); | ||||
|     } | ||||
| 
 | ||||
|     private final boolean softBreakAddsNewLine; | ||||
| 
 | ||||
|     protected CorePlugin(boolean softBreakAddsNewLine) { | ||||
|         this.softBreakAddsNewLine = softBreakAddsNewLine; | ||||
|     protected CorePlugin() { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @ -78,7 +70,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|         listItem(builder); | ||||
|         thematicBreak(builder); | ||||
|         heading(builder); | ||||
|         softLineBreak(builder, softBreakAddsNewLine); | ||||
|         softLineBreak(builder); | ||||
|         hardLineBreak(builder); | ||||
|         paragraph(builder); | ||||
|         link(builder); | ||||
| @ -341,16 +333,12 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private static void softLineBreak(@NonNull MarkwonVisitor.Builder builder, final boolean softBreakAddsNewLine) { | ||||
|     private static void softLineBreak(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(SoftLineBreak.class, new MarkwonVisitor.NodeVisitor<SoftLineBreak>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull SoftLineBreak softLineBreak) { | ||||
|                 if (softBreakAddsNewLine) { | ||||
|                     visitor.ensureNewLine(); | ||||
|                 } else { | ||||
|                 visitor.builder().append(' '); | ||||
|             } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -126,7 +126,7 @@ public class MarkwonBuilderImplTest { | ||||
|         }; | ||||
| 
 | ||||
|         // our subclass | ||||
|         final CorePlugin corePlugin = new CorePlugin(false) { | ||||
|         final CorePlugin corePlugin = new CorePlugin() { | ||||
| 
 | ||||
|         }; | ||||
| 
 | ||||
|  | ||||
| @ -2,6 +2,8 @@ package ru.noties.markwon.core; | ||||
| 
 | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.text.method.MovementMethod; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import org.commonmark.node.BlockQuote; | ||||
| import org.commonmark.node.BulletList; | ||||
| @ -46,6 +48,7 @@ import ru.noties.markwon.SpannableBuilder; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.ArgumentMatchers.eq; | ||||
| @ -223,26 +226,9 @@ public class CorePluginTest { | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void softbreak_adds_new_line_default() { | ||||
|         // default is false | ||||
|         softbreak_adds_new_line(CorePlugin.create(), false); | ||||
|     } | ||||
|     public void softbreak() { | ||||
| 
 | ||||
|     @Test | ||||
|     public void softbreak_adds_new_line_false() { | ||||
|         // a space character will be added | ||||
|         softbreak_adds_new_line(CorePlugin.create(false), false); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void softbreak_adds_new_line_true() { | ||||
|         // a new line will be added | ||||
|         softbreak_adds_new_line(CorePlugin.create(true), true); | ||||
|     } | ||||
| 
 | ||||
|     private static void softbreak_adds_new_line( | ||||
|             @NonNull CorePlugin plugin, | ||||
|             boolean softBreakAddsNewLine) { | ||||
|         final CorePlugin plugin = CorePlugin.create(); | ||||
| 
 | ||||
|         final MarkwonVisitor.Builder builder = mock(MarkwonVisitor.Builder.class); | ||||
|         when(builder.on(any(Class.class), any(MarkwonVisitor.NodeVisitor.class))).thenReturn(builder); | ||||
| @ -259,8 +245,6 @@ public class CorePluginTest { | ||||
|         final MarkwonVisitor.NodeVisitor<SoftLineBreak> nodeVisitor = captor.getValue(); | ||||
|         final MarkwonVisitor visitor = mock(MarkwonVisitor.class); | ||||
| 
 | ||||
|         if (!softBreakAddsNewLine) { | ||||
| 
 | ||||
|         // we must mock SpannableBuilder and verify that it has a space character appended | ||||
|         final SpannableBuilder spannableBuilder = mock(SpannableBuilder.class); | ||||
|         when(visitor.builder()).thenReturn(spannableBuilder); | ||||
| @ -268,12 +252,37 @@ public class CorePluginTest { | ||||
| 
 | ||||
|         verify(visitor, times(1)).builder(); | ||||
|         verify(spannableBuilder, times(1)).append(eq(' ')); | ||||
|     } | ||||
| 
 | ||||
|         } else { | ||||
|     @Test | ||||
|     public void implicit_movement_method_after_set_text_added() { | ||||
|         // validate that CorePlugin will implicitly add LinkMovementMethod if one is missing | ||||
|         final TextView textView = mock(TextView.class); | ||||
|         when(textView.getMovementMethod()).thenReturn(null); | ||||
| 
 | ||||
|             nodeVisitor.visit(visitor, mock(SoftLineBreak.class)); | ||||
|         final CorePlugin plugin = CorePlugin.create(); | ||||
| 
 | ||||
|             verify(visitor, times(1)).ensureNewLine(); | ||||
|         } | ||||
|         assertNull(textView.getMovementMethod()); | ||||
| 
 | ||||
|         plugin.afterSetText(textView); | ||||
| 
 | ||||
|         final ArgumentCaptor<MovementMethod> captor = ArgumentCaptor.forClass(MovementMethod.class); | ||||
|         verify(textView, times(1)).setMovementMethod(captor.capture()); | ||||
| 
 | ||||
|         assertNotNull(captor.getValue()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void implicit_movement_method_after_set_text_no_op() { | ||||
|         // validate that CorePlugin won't change movement method if one is present on a TextView | ||||
| 
 | ||||
|         final TextView textView = mock(TextView.class); | ||||
|         when(textView.getMovementMethod()).thenReturn(mock(MovementMethod.class)); | ||||
| 
 | ||||
|         final CorePlugin plugin = CorePlugin.create(); | ||||
| 
 | ||||
|         plugin.afterSetText(textView); | ||||
| 
 | ||||
|         verify(textView, times(0)).setMovementMethod(any(MovementMethod.class)); | ||||
|     } | ||||
| } | ||||
| @ -73,7 +73,7 @@ abstract class BaseSuiteTest { | ||||
|   @NonNull | ||||
|   Markwon markwon() { | ||||
|     return Markwon.builder(RuntimeEnvironment.application) | ||||
|       .usePlugin(CorePlugin.create(softBreakAddsNewLine())) | ||||
|       .usePlugin(CorePlugin.create()) | ||||
|       .usePlugin(new AbstractMarkwonPlugin() { | ||||
|         @Override | ||||
|         public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { | ||||
| @ -99,10 +99,6 @@ abstract class BaseSuiteTest { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   boolean softBreakAddsNewLine() { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   private static final Map<Class<? extends Node>, SpanFactory> CORE_NODES; | ||||
| 
 | ||||
|   static { | ||||
|  | ||||
| @ -1,39 +0,0 @@ | ||||
| package ru.noties.markwon.core.suite; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.robolectric.RobolectricTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| 
 | ||||
| import ru.noties.markwon.test.TestSpan.Document; | ||||
| 
 | ||||
| import static ru.noties.markwon.test.TestSpan.document; | ||||
| import static ru.noties.markwon.test.TestSpan.text; | ||||
| 
 | ||||
| @RunWith(RobolectricTestRunner.class) | ||||
| @Config(manifest = Config.NONE) | ||||
| public class SoftBreakAddsNewLineTest extends BaseSuiteTest { | ||||
| 
 | ||||
|   /* | ||||
| hello there! | ||||
| this one is on the next line | ||||
| hard break to the full extend | ||||
|    */ | ||||
| 
 | ||||
|   @Test | ||||
|   public void test() { | ||||
| 
 | ||||
|     final Document document = document( | ||||
|       text("hello there!\n"), | ||||
|       text("this one is on the next line\n"), | ||||
|       text("hard break to the full extend") | ||||
|     ); | ||||
| 
 | ||||
|     matchInput("soft-break-adds-new-line.md", document); | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   boolean softBreakAddsNewLine() { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
| @ -25,9 +25,4 @@ public class SoftBreakTest extends BaseSuiteTest { | ||||
| 
 | ||||
|     matchInput("soft-break.md", document); | ||||
|   } | ||||
| 
 | ||||
|     @Override | ||||
|     boolean softBreakAddsNewLine() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -109,7 +109,7 @@ public class PriorityProcessorTest { | ||||
|     public void subclass_found() { | ||||
|         // when a plugin comes after another, but _another_ was subclassed and placed in the list | ||||
| 
 | ||||
|         final MarkwonPlugin core = new CorePlugin(false) { | ||||
|         final MarkwonPlugin core = new CorePlugin() { | ||||
|         }; | ||||
|         final MarkwonPlugin plugin = new AbstractMarkwonPlugin() { | ||||
|             @NonNull | ||||
|  | ||||
| @ -30,6 +30,13 @@ public class TablePlugin extends AbstractMarkwonPlugin { | ||||
|         void configureTheme(@NonNull TableTheme.Builder builder); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Factory method to create a {@link TablePlugin} with default {@link TableTheme} instance | ||||
|      * (obtained via {@link TableTheme#create(Context)} method) | ||||
|      * | ||||
|      * @see #create(TableTheme) | ||||
|      * @see #create(ThemeConfigure) | ||||
|      */ | ||||
|     @NonNull | ||||
|     public static TablePlugin create(@NonNull Context context) { | ||||
|         return new TablePlugin(TableTheme.create(context)); | ||||
|  | ||||
| @ -81,6 +81,8 @@ public class RecyclerActivity extends Activity { | ||||
|                 .usePlugin(CorePlugin.create()) | ||||
|                 .usePlugin(ImagesPlugin.createWithAssets(context)) | ||||
|                 .usePlugin(SvgPlugin.create(context.getResources())) | ||||
|                 // although we will be rendering table differently we still need | ||||
|                 // to register commonmark-java tables extension (which TablePlugin does) | ||||
|                 .usePlugin(TablePlugin.create(context)) | ||||
|                 .usePlugin(HtmlPlugin.create()) | ||||
|                 .usePlugin(new AbstractMarkwonPlugin() { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user