Add editor documentation page
This commit is contained in:
		
							parent
							
								
									bd53c014a1
								
							
						
					
					
						commit
						2488c1047b
					
				| @ -22,7 +22,7 @@ listed in <Link name="commonmark-spec" /> are supported (including support for * | ||||
| **markdown tables**, **images** and **syntax highlight**). | ||||
| 
 | ||||
| Since version <Badge text="4.2.0" /> **Markwon** comes with an [editor] to _highlight_ markdown input | ||||
| as user types for example in **EditText**. | ||||
| as user types (for example in **EditText**). | ||||
| 
 | ||||
| [editor]: /docs/v4/editor/ | ||||
| 
 | ||||
|  | ||||
| @ -18,8 +18,116 @@ video { | ||||
| 
 | ||||
| ## Getting started with editor | ||||
| 
 | ||||
| ```java | ||||
| // obtain Markwon instance | ||||
| final Markwon markwon = Markwon.create(this); | ||||
| 
 | ||||
| // create editor | ||||
| final MarkwonEditor editor = MarkwonEditor.create(markwon); | ||||
| 
 | ||||
| // set edit listener | ||||
| editText.addTextChangedListener(MarkwonEditorTextWatcher.withProcess(editor)); | ||||
| ``` | ||||
| 
 | ||||
| The code above _highlights_ in-place which is OK for relatively small markdown inputs. | ||||
| If you wish to offload main thread and highlight in background use `withPreRender` | ||||
| `MarkwonEditorTextWatcher`: | ||||
| 
 | ||||
| ```java | ||||
| editText.addTextChangedListener(MarkwonEditorTextWatcher.withPreRender( | ||||
|         editor, | ||||
|         Executors.newCachedThreadPool(), | ||||
|         editText)); | ||||
| ``` | ||||
| 
 | ||||
| `MarkwonEditorTextWatcher` automatically triggers markdown highlight when text in `EditText` changes. | ||||
| But you still can invoke `MarkwonEditor` manually: | ||||
| 
 | ||||
| ```java | ||||
| editor.process(editText.getText()); | ||||
| 
 | ||||
| // please note that MarkwonEditor operates on caller thread, | ||||
| // if you wish to execute this operation in background - this method | ||||
| // must be called from background thread | ||||
| editor.preRender(editText.getText(), new MarkwonEditor.PreRenderResultListener() { | ||||
|     @Override | ||||
|     public void onPreRenderResult(@NonNull MarkwonEditor.PreRenderResult result) { | ||||
|         // it's wise to check if rendered result is for the same input, | ||||
|         // for example by matching raw input | ||||
|         if (editText.getText().toString().equals(result.resultEditable().toString())) { | ||||
|              | ||||
|             // if you are in background thread do not forget | ||||
|             // to execute dispatch in main thread | ||||
|             result.dispatchTo(editText.getText()); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| :::warning Implementation Detail | ||||
| It must be mentioned that highlight is implemented via text diff. Everything | ||||
| that is present in raw markdown input and missing from rendered result is considered | ||||
| that is present in raw markdown input but missing from rendered result is considered | ||||
| to be _punctuation_. | ||||
| ::: | ||||
| ::: | ||||
| 
 | ||||
| :::danger Tables and LaTeX | ||||
| Tables and LaTeX nodes won't be rendered correctly. They will be treated as _punctuation_ | ||||
| as whole. This comes from their implementation - they are _mocked_ and do not present | ||||
| in final result as text and thus cannot be _diffed_.  | ||||
| ::: | ||||
| 
 | ||||
| ## Custom punctuation span | ||||
| 
 | ||||
| By default `MarkwonEditor` uses lighter text color of widget to customize punctuation. | ||||
| If you wish to use a different span you can use `withPunctuationSpan` configuration step: | ||||
| 
 | ||||
| ```java | ||||
| final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|         .withPunctuationSpan(CustomPunctuationSpan.class, CustomPunctuationSpan::new) | ||||
|         .build(); | ||||
| ``` | ||||
| 
 | ||||
| ```java | ||||
| public class CustomPunctuationSpan extends ForegroundColorSpan { | ||||
|     CustomPunctuationSpan() { | ||||
|         super(0xFFFF0000); // RED | ||||
|     } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Additional handling | ||||
| 
 | ||||
| In order to additionally highlight portions of markdown input (for example make text wrapped with `**` | ||||
| symbols **bold**) `EditSpanHandler` can be used: | ||||
| 
 | ||||
| ```java | ||||
| final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|         // This is required for edit-span cache | ||||
|         // We could use Markwon `StrongEmphasisSpan` here, but I use a different | ||||
|         //  one to indicate that those are completely unrelated spans and must be | ||||
|         //  treated differently. | ||||
|         .includeEditSpan(Bold.class, Bold::new) | ||||
|         .withEditSpanHandler(new MarkwonEditor.EditSpanHandler() { | ||||
|             @Override | ||||
|             public void handle( | ||||
|                     @NonNull MarkwonEditor.EditSpanStore store, | ||||
|                     @NonNull Editable editable, | ||||
|                     @NonNull String input, | ||||
|                     @NonNull Object span, | ||||
|                     int spanStart, | ||||
|                     int spanTextLength) { | ||||
|                 if (span instanceof StrongEmphasisSpan) { | ||||
|                     editable.setSpan( | ||||
|                             // `includeEditSpan(Bold.class, Bold::new)` ensured that we have | ||||
|                             //      a span here to use (either reuse existing or create a new one) | ||||
|                             store.get(Bold.class), | ||||
|                             spanStart, | ||||
|                             // we know that strong emphasis is delimited with 2 characters on both sides | ||||
|                             spanStart + spanTextLength + 4, | ||||
|                             Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         .build(); | ||||
| ``` | ||||
|  | ||||
| @ -64,13 +64,13 @@ public class EditorActivity extends Activity { | ||||
|     private void simple_process() { | ||||
|         // Process highlight in-place (right after text has changed) | ||||
| 
 | ||||
|         // obtain Markwon instance | ||||
| // obtain Markwon instance | ||||
|         final Markwon markwon = Markwon.create(this); | ||||
| 
 | ||||
|         // create editor | ||||
| // create editor | ||||
|         final MarkwonEditor editor = MarkwonEditor.create(markwon); | ||||
| 
 | ||||
|         // set edit listener | ||||
| // set edit listener | ||||
|         editText.addTextChangedListener(MarkwonEditorTextWatcher.withProcess(editor)); | ||||
|     } | ||||
| 
 | ||||
| @ -80,6 +80,25 @@ public class EditorActivity extends Activity { | ||||
|         final Markwon markwon = Markwon.create(this); | ||||
|         final MarkwonEditor editor = MarkwonEditor.create(markwon); | ||||
| 
 | ||||
| editor.process(editText.getText()); | ||||
| 
 | ||||
| // please note that MarkwonEditor operates on caller thread, | ||||
| // fi you wish to execute this operation in background - this method | ||||
| // must be called from background thread | ||||
| editor.preRender(editText.getText(), new MarkwonEditor.PreRenderResultListener() { | ||||
|     @Override | ||||
|     public void onPreRenderResult(@NonNull MarkwonEditor.PreRenderResult result) { | ||||
|         // it's wise to check if rendered result is for the same input, | ||||
|         // for example by matching raw input | ||||
|         if (editText.getText().toString().equals(result.resultEditable().toString())) { | ||||
| 
 | ||||
|             // if you are in background thread do not forget | ||||
|             // to execute dispatch in main thread | ||||
|             result.dispatchTo(editText.getText()); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| 
 | ||||
|         editText.addTextChangedListener(MarkwonEditorTextWatcher.withPreRender( | ||||
|                 editor, | ||||
|                 Executors.newCachedThreadPool(), | ||||
| @ -89,9 +108,9 @@ public class EditorActivity extends Activity { | ||||
|     private void custom_punctuation_span() { | ||||
|         // Use own punctuation span | ||||
| 
 | ||||
|         final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|                 .withPunctuationSpan(CustomPunctuationSpan.class, CustomPunctuationSpan::new) | ||||
|                 .build(); | ||||
| final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|         .withPunctuationSpan(CustomPunctuationSpan.class, CustomPunctuationSpan::new) | ||||
|         .build(); | ||||
| 
 | ||||
|         editText.addTextChangedListener(MarkwonEditorTextWatcher.withProcess(editor)); | ||||
|     } | ||||
| @ -99,35 +118,35 @@ public class EditorActivity extends Activity { | ||||
|     private void additional_edit_span() { | ||||
|         // An additional span is used to highlight strong-emphasis | ||||
| 
 | ||||
|         final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|                 // This is required for edit-span cache | ||||
|                 // We could use Markwon `StrongEmphasisSpan` here, but I use a different | ||||
|                 //  one to indicate that those are completely unrelated spans and must be | ||||
|                 //  treated differently. | ||||
|                 .includeEditSpan(Bold.class, Bold::new) | ||||
|                 .withEditSpanHandler(new MarkwonEditor.EditSpanHandler() { | ||||
|                     @Override | ||||
|                     public void handle( | ||||
|                             @NonNull MarkwonEditor.EditSpanStore store, | ||||
|                             @NonNull Editable editable, | ||||
|                             @NonNull String input, | ||||
|                             @NonNull Object span, | ||||
|                             int spanStart, | ||||
|                             int spanTextLength) { | ||||
|                         if (span instanceof StrongEmphasisSpan) { | ||||
|                             editable.setSpan( | ||||
|                                     // `includeEditSpan(Bold.class, Bold::new)` ensured that we have | ||||
|                                     //      a span here to use (either reuse existing or create a new one) | ||||
|                                     store.get(Bold.class), | ||||
|                                     spanStart, | ||||
|                                     // we know that strong emphasis is delimited with 2 characters on both sides | ||||
|                                     spanStart + spanTextLength + 4, | ||||
|                                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ||||
|                             ); | ||||
|                         } | ||||
|                     } | ||||
|                 }) | ||||
|                 .build(); | ||||
| final MarkwonEditor editor = MarkwonEditor.builder(Markwon.create(this)) | ||||
|         // This is required for edit-span cache | ||||
|         // We could use Markwon `StrongEmphasisSpan` here, but I use a different | ||||
|         //  one to indicate that those are completely unrelated spans and must be | ||||
|         //  treated differently. | ||||
|         .includeEditSpan(Bold.class, Bold::new) | ||||
|         .withEditSpanHandler(new MarkwonEditor.EditSpanHandler() { | ||||
|             @Override | ||||
|             public void handle( | ||||
|                     @NonNull MarkwonEditor.EditSpanStore store, | ||||
|                     @NonNull Editable editable, | ||||
|                     @NonNull String input, | ||||
|                     @NonNull Object span, | ||||
|                     int spanStart, | ||||
|                     int spanTextLength) { | ||||
|                 if (span instanceof StrongEmphasisSpan) { | ||||
|                     editable.setSpan( | ||||
|                             // `includeEditSpan(Bold.class, Bold::new)` ensured that we have | ||||
|                             //      a span here to use (either reuse existing or create a new one) | ||||
|                             store.get(Bold.class), | ||||
|                             spanStart, | ||||
|                             // we know that strong emphasis is delimited with 2 characters on both sides | ||||
|                             spanStart + spanTextLength + 4, | ||||
|                             Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         .build(); | ||||
| 
 | ||||
|         editText.addTextChangedListener(MarkwonEditorTextWatcher.withProcess(editor)); | ||||
|     } | ||||
| @ -316,11 +335,11 @@ public class EditorActivity extends Activity { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static class CustomPunctuationSpan extends ForegroundColorSpan { | ||||
|         CustomPunctuationSpan() { | ||||
|             super(0xFFFF0000); // RED | ||||
|         } | ||||
| private static class CustomPunctuationSpan extends ForegroundColorSpan { | ||||
|     CustomPunctuationSpan() { | ||||
|         super(0xFFFF0000); // RED | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     private static class Bold extends MetricAffectingSpan { | ||||
|         public Bold() { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov