Core functionality plugin
This commit is contained in:
		
							parent
							
								
									498c811987
								
							
						
					
					
						commit
						3526e16565
					
				| @ -41,17 +41,17 @@ | ||||
|                 <!--<data--> | ||||
|                 <!--android:host="*"--> | ||||
|                 <!--android:scheme="http"--> | ||||
|                 <!--android:mimeType="text/markdown"/>--> | ||||
|                 <!--android:mimeType="text/toMarkdown"/>--> | ||||
| 
 | ||||
|                 <!--<data--> | ||||
|                 <!--android:host="*"--> | ||||
|                 <!--android:scheme="file"--> | ||||
|                 <!--android:mimeType="text/markdown"/>--> | ||||
|                 <!--android:mimeType="text/toMarkdown"/>--> | ||||
| 
 | ||||
|                 <!--<data--> | ||||
|                 <!--android:host="*"--> | ||||
|                 <!--android:scheme="https"--> | ||||
|                 <!--android:mimeType="text/markdown"/>--> | ||||
|                 <!--android:mimeType="text/toMarkdown"/>--> | ||||
| 
 | ||||
|                 <data android:pathPattern=".*\\.markdown" /> | ||||
|                 <data android:pathPattern=".*\\.mdown" /> | ||||
|  | ||||
| @ -71,7 +71,7 @@ public class MainActivity extends Activity { | ||||
|                     .use(new CorePlugin()) | ||||
|                     .use(TaskListPlugin.create(new TaskListDrawable(0xffff0000, 0xffff0000, -1))) | ||||
|                     .build(); | ||||
|             final CharSequence markdown = markwon2.markdown("**hello _dear_** `code`\n\n- [ ] first\n- [x] second"); | ||||
|             final CharSequence markdown = markwon2.toMarkdown("**hello _dear_** `code`\n\n- [ ] first\n- [x] second"); | ||||
|             textView.setText(markdown); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @ -104,7 +104,7 @@ public class MarkdownRenderer { | ||||
| 
 | ||||
|                 final long end = SystemClock.uptimeMillis(); | ||||
| 
 | ||||
|                 Debug.i("markdown rendered: %d ms", end - start); | ||||
|                 Debug.i("toMarkdown rendered: %d ms", end - start); | ||||
| 
 | ||||
|                 if (!isCancelled()) { | ||||
|                     handler.post(new Runnable() { | ||||
|  | ||||
| @ -60,7 +60,7 @@ public class MarkwonViewHelper implements IMarkwonView { | ||||
|         this.provider = provider; | ||||
|         this.configuration = provider.provide(textView.getContext()); | ||||
|         if (!TextUtils.isEmpty(markdown)) { | ||||
|             // invalidate rendered markdown | ||||
|             // invalidate rendered toMarkdown | ||||
|             setMarkdown(markdown); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -35,12 +35,12 @@ public abstract class AbstractMarkwonPlugin implements MarkwonPlugin { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) { | ||||
|     public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void afterSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) { | ||||
|     public void afterSetText(@NonNull TextView textView, @NonNull CharSequence markdown) { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -48,12 +48,12 @@ public abstract class Markwon { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Parses submitted raw markdown, converts it to CharSequence (with Spannables) | ||||
|      * Parses submitted raw toMarkdown, converts it to CharSequence (with Spannables) | ||||
|      * and applies it to view | ||||
|      * | ||||
|      * @param view          {@link TextView} to set markdown into | ||||
|      * @param view          {@link TextView} to set toMarkdown into | ||||
|      * @param configuration a {@link MarkwonConfiguration} instance | ||||
|      * @param markdown      raw markdown String (for example: {@code `**Hello**`}) | ||||
|      * @param markdown      raw toMarkdown String (for example: {@code `**Hello**`}) | ||||
|      * @see #markdown(MarkwonConfiguration, String) | ||||
|      * @see #setText(TextView, CharSequence) | ||||
|      * @see MarkwonConfiguration | ||||
| @ -69,13 +69,13 @@ public abstract class Markwon { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Helper method to apply parsed markdown. | ||||
|      * Helper method to apply parsed toMarkdown. | ||||
|      * <p> | ||||
|      * Since 1.0.6 redirects it\'s call to {@link #setText(TextView, CharSequence, MovementMethod)} | ||||
|      * with LinkMovementMethod as an argument to preserve current API. | ||||
|      * | ||||
|      * @param view {@link TextView} to set markdown into | ||||
|      * @param text parsed markdown | ||||
|      * @param view {@link TextView} to set toMarkdown into | ||||
|      * @param text parsed toMarkdown | ||||
|      * @see #setText(TextView, CharSequence, MovementMethod) | ||||
|      * @since 1.0.0 | ||||
|      */ | ||||
| @ -84,13 +84,13 @@ public abstract class Markwon { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Helper method to apply parsed markdown with additional argument of a MovementMethod. Used | ||||
|      * Helper method to apply parsed toMarkdown with additional argument of a MovementMethod. Used | ||||
|      * to workaround problems that occur when using system LinkMovementMethod (for example: | ||||
|      * https://issuetracker.google.com/issues/37068143). As a better alternative to it consider | ||||
|      * using: https://github.com/saket/Better-Link-Movement-Method | ||||
|      * | ||||
|      * @param view           TextView to set markdown into | ||||
|      * @param text           parsed markdown | ||||
|      * @param view           TextView to set toMarkdown into | ||||
|      * @param text           parsed toMarkdown | ||||
|      * @param movementMethod an implementation if MovementMethod or null | ||||
|      * @see #scheduleDrawables(TextView) | ||||
|      * @see #scheduleTableRows(TextView) | ||||
| @ -102,7 +102,7 @@ public abstract class Markwon { | ||||
|         unscheduleTableRows(view); | ||||
| 
 | ||||
|         // @since 2.0.1 we must measure ordered-list-item-spans before applying text to a TextView. | ||||
|         // if markdown has a lot of ordered list items (or text size is relatively big, or block-margin | ||||
|         // if toMarkdown has a lot of ordered list items (or text size is relatively big, or block-margin | ||||
|         // is relatively small) then this list won't be rendered properly: it will take correct | ||||
|         // layout (width and margin) but will be clipped if margin is not _consistent_ between calls. | ||||
|         OrderedListItemSpan.measure(view, text); | ||||
| @ -117,11 +117,11 @@ public abstract class Markwon { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns parsed markdown with default {@link MarkwonConfiguration} obtained from {@link Context} | ||||
|      * Returns parsed toMarkdown with default {@link MarkwonConfiguration} obtained from {@link Context} | ||||
|      * | ||||
|      * @param context  {@link Context} | ||||
|      * @param markdown raw markdown | ||||
|      * @return parsed markdown | ||||
|      * @param markdown raw toMarkdown | ||||
|      * @return parsed toMarkdown | ||||
|      * @since 1.0.0 | ||||
|      */ | ||||
|     @NonNull | ||||
| @ -131,11 +131,11 @@ public abstract class Markwon { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns parsed markdown with provided {@link MarkwonConfiguration} | ||||
|      * Returns parsed toMarkdown with provided {@link MarkwonConfiguration} | ||||
|      * | ||||
|      * @param configuration a {@link MarkwonConfiguration} | ||||
|      * @param markdown      raw markdown | ||||
|      * @return parsed markdown | ||||
|      * @param markdown      raw toMarkdown | ||||
|      * @return parsed toMarkdown | ||||
|      * @see MarkwonConfiguration | ||||
|      * @since 1.0.0 | ||||
|      */ | ||||
|  | ||||
| @ -2,6 +2,7 @@ package ru.noties.markwon; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import org.commonmark.node.Node; | ||||
| 
 | ||||
| @ -18,8 +19,13 @@ public abstract class Markwon2 { | ||||
|     @NonNull | ||||
|     public abstract CharSequence render(@NonNull Node node); | ||||
| 
 | ||||
|     // parse + render | ||||
|     @NonNull | ||||
|     public abstract CharSequence markdown(@NonNull String input); | ||||
|     public abstract CharSequence toMarkdown(@NonNull String input); | ||||
| 
 | ||||
|     public abstract void setMarkdown(@NonNull TextView textView, @NonNull String markdown); | ||||
| 
 | ||||
|     public abstract void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown); | ||||
| 
 | ||||
|     public interface Builder { | ||||
| 
 | ||||
|  | ||||
| @ -46,7 +46,7 @@ class MarkwonBuilderImpl implements Markwon2.Builder { | ||||
| 
 | ||||
|         return new MarkwonImpl( | ||||
|                 parserBuilder.build(), | ||||
|                 visitorBuilder.build(themeBuilder.build(), configurationBuilder.build()), | ||||
|                 visitorBuilder.build(configurationBuilder.build(themeBuilder.build())), | ||||
|                 Collections.unmodifiableList(plugins) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @ -20,7 +20,7 @@ public class MarkwonConfiguration { | ||||
|     // creates default configuration | ||||
|     @NonNull | ||||
|     public static MarkwonConfiguration create(@NonNull Context context) { | ||||
|         return new Builder(context).build(); | ||||
|         return new Builder(context).build(MarkwonTheme.create(context)); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
| @ -28,9 +28,8 @@ public class MarkwonConfiguration { | ||||
|         return new Builder(context); | ||||
|     } | ||||
| 
 | ||||
|     @Deprecated | ||||
|     private final MarkwonTheme theme; | ||||
| 
 | ||||
|     private final MarkwonTheme theme; | ||||
|     private final AsyncDrawable.Loader asyncDrawableLoader; | ||||
|     private final SyntaxHighlight syntaxHighlight; | ||||
|     private final LinkSpan.Resolver linkResolver; | ||||
| @ -65,7 +64,6 @@ public class MarkwonConfiguration { | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Deprecated | ||||
|     public MarkwonTheme theme() { | ||||
|         return theme; | ||||
|     } | ||||
| @ -137,7 +135,6 @@ public class MarkwonConfiguration { | ||||
| 
 | ||||
|         private final Context context; | ||||
| 
 | ||||
|         @Deprecated | ||||
|         private MarkwonTheme theme; | ||||
|         private AsyncDrawable.Loader asyncDrawableLoader; | ||||
|         private SyntaxHighlight syntaxHighlight; | ||||
| @ -169,12 +166,12 @@ public class MarkwonConfiguration { | ||||
|             this.htmlAllowNonClosedTags = configuration.htmlAllowNonClosedTags; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         @Deprecated | ||||
|         public Builder theme(@NonNull MarkwonTheme theme) { | ||||
|             this.theme = theme; | ||||
|             return this; | ||||
|         } | ||||
| //        @NonNull | ||||
| //        @Deprecated | ||||
| //        public Builder theme(@NonNull MarkwonTheme theme) { | ||||
| //            this.theme = theme; | ||||
| //            return this; | ||||
| //        } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public Builder asyncDrawableLoader(@NonNull AsyncDrawable.Loader asyncDrawableLoader) { | ||||
| @ -263,11 +260,9 @@ public class MarkwonConfiguration { | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         public MarkwonConfiguration build() { | ||||
|         public MarkwonConfiguration build(@NonNull MarkwonTheme theme) { | ||||
| 
 | ||||
|             if (theme == null) { | ||||
|                 theme = MarkwonTheme.create(context); | ||||
|             } | ||||
|             this.theme = theme; | ||||
| 
 | ||||
|             if (asyncDrawableLoader == null) { | ||||
|                 asyncDrawableLoader = new AsyncDrawableLoaderNoOp(); | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package ru.noties.markwon; | ||||
| 
 | ||||
| import android.support.annotation.NonNull; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import org.commonmark.node.Node; | ||||
| import org.commonmark.parser.Parser; | ||||
| @ -42,7 +43,26 @@ class MarkwonImpl extends Markwon2 { | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public CharSequence markdown(@NonNull String input) { | ||||
|     public CharSequence toMarkdown(@NonNull String input) { | ||||
|         return render(parse(input)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setMarkdown(@NonNull TextView textView, @NonNull String markdown) { | ||||
|         setParsedMarkdown(textView, toMarkdown(markdown)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setParsedMarkdown(@NonNull TextView textView, @NonNull CharSequence markdown) { | ||||
| 
 | ||||
|         for (MarkwonPlugin plugin : plugins) { | ||||
|             plugin.beforeSetText(textView, markdown); | ||||
|         } | ||||
| 
 | ||||
|         textView.setText(markdown); | ||||
| 
 | ||||
|         for (MarkwonPlugin plugin : plugins) { | ||||
|             plugin.afterSetText(textView, markdown); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -23,7 +23,7 @@ public interface MarkwonPlugin { | ||||
|     @NonNull | ||||
|     String processMarkdown(@NonNull String markdown); | ||||
| 
 | ||||
|     void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder); | ||||
|     void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown); | ||||
| 
 | ||||
|     void afterSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder); | ||||
|     void afterSetText(@NonNull TextView textView, @NonNull CharSequence markdown); | ||||
| } | ||||
|  | ||||
| @ -20,14 +20,17 @@ public interface MarkwonVisitor extends Visitor { | ||||
|         <N extends Node> Builder on(@NonNull Class<N> node, @NonNull NodeVisitor<N> nodeVisitor); | ||||
| 
 | ||||
|         @NonNull | ||||
|         MarkwonVisitor build(@NonNull MarkwonTheme theme, @NonNull MarkwonConfiguration configuration); | ||||
|         MarkwonVisitor build(@NonNull MarkwonConfiguration configuration); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     MarkwonConfiguration configuration(); | ||||
| 
 | ||||
|     @NonNull | ||||
|     MarkwonTheme theme(); | ||||
| 
 | ||||
|     @NonNull | ||||
|     MarkwonConfiguration configuration(); | ||||
|     SpannableFactory factory(); | ||||
| 
 | ||||
|     @NonNull | ||||
|     SpannableBuilder builder(); | ||||
|  | ||||
| @ -37,19 +37,21 @@ class MarkwonVisitorImpl implements MarkwonVisitor { | ||||
| 
 | ||||
|     private final Map<Class<? extends Node>, NodeVisitor<? extends Node>> nodes; | ||||
| 
 | ||||
|     private final MarkwonTheme theme; | ||||
|     private final MarkwonConfiguration configuration; | ||||
|     private final MarkwonTheme theme; | ||||
|     private final SpannableFactory factory; | ||||
| 
 | ||||
|     private final SpannableBuilder builder = new SpannableBuilder(); | ||||
| 
 | ||||
|     private int blockQuoteIndent; | ||||
|     private int listLevel; | ||||
| 
 | ||||
|     private MarkwonVisitorImpl( | ||||
|             @NonNull MarkwonTheme theme, | ||||
|             @NonNull MarkwonConfiguration configuration, | ||||
|             @NonNull Map<Class<? extends Node>, NodeVisitor<? extends Node>> nodes) { | ||||
|         this.theme = theme; | ||||
|         this.configuration = configuration; | ||||
|         this.theme = configuration.theme(); | ||||
|         this.factory = configuration.factory(); | ||||
|         this.nodes = nodes; | ||||
|     } | ||||
| 
 | ||||
| @ -173,6 +175,12 @@ class MarkwonVisitorImpl implements MarkwonVisitor { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MarkwonConfiguration configuration() { | ||||
|         return configuration; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MarkwonTheme theme() { | ||||
| @ -181,8 +189,8 @@ class MarkwonVisitorImpl implements MarkwonVisitor { | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public MarkwonConfiguration configuration() { | ||||
|         return configuration; | ||||
|     public SpannableFactory factory() { | ||||
|         return factory; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
| @ -280,9 +288,8 @@ class MarkwonVisitorImpl implements MarkwonVisitor { | ||||
| 
 | ||||
|         @NonNull | ||||
|         @Override | ||||
|         public MarkwonVisitor build(@NonNull MarkwonTheme theme, @NonNull MarkwonConfiguration configuration) { | ||||
|         public MarkwonVisitor build(@NonNull MarkwonConfiguration configuration) { | ||||
|             return new MarkwonVisitorImpl( | ||||
|                     theme, | ||||
|                     configuration, | ||||
|                     Collections.unmodifiableMap(nodes)); | ||||
|         } | ||||
|  | ||||
| @ -9,17 +9,24 @@ import org.commonmark.node.BulletList; | ||||
| import org.commonmark.node.Code; | ||||
| import org.commonmark.node.Emphasis; | ||||
| import org.commonmark.node.FencedCodeBlock; | ||||
| import org.commonmark.node.HardLineBreak; | ||||
| import org.commonmark.node.Heading; | ||||
| import org.commonmark.node.Image; | ||||
| import org.commonmark.node.IndentedCodeBlock; | ||||
| import org.commonmark.node.Link; | ||||
| import org.commonmark.node.ListBlock; | ||||
| import org.commonmark.node.ListItem; | ||||
| import org.commonmark.node.Node; | ||||
| import org.commonmark.node.OrderedList; | ||||
| import org.commonmark.node.Paragraph; | ||||
| import org.commonmark.node.SoftLineBreak; | ||||
| import org.commonmark.node.StrongEmphasis; | ||||
| import org.commonmark.node.Text; | ||||
| import org.commonmark.node.ThematicBreak; | ||||
| 
 | ||||
| import ru.noties.markwon.AbstractMarkwonPlugin; | ||||
| import ru.noties.markwon.MarkwonConfiguration; | ||||
| import ru.noties.markwon.MarkwonVisitor; | ||||
| import ru.noties.markwon.SpannableBuilder; | ||||
| import ru.noties.markwon.spans.OrderedListItemSpan; | ||||
| 
 | ||||
| public class CorePlugin extends AbstractMarkwonPlugin { | ||||
| @ -30,6 +37,25 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     // todo: softBreak adds new line should be here (or maybe removed even?) | ||||
| 
 | ||||
|     // todo: add a simple HTML handler | ||||
|     // todo: configure primitive images (without okhttp -> just HttpUrlConnection and simple types (static, data) | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CorePlugin create() { | ||||
|         return create(false); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CorePlugin create(boolean softBreakAddsNewLine) { | ||||
|         return new CorePlugin(softBreakAddsNewLine); | ||||
|     } | ||||
| 
 | ||||
|     private final boolean softBreakAddsNewLine; | ||||
| 
 | ||||
|     protected CorePlugin(boolean softBreakAddsNewLine) { | ||||
|         this.softBreakAddsNewLine = softBreakAddsNewLine; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         text(builder); | ||||
| @ -43,11 +69,17 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|         orderedList(builder); | ||||
|         listItem(builder); | ||||
|         thematicBreak(builder); | ||||
|         heading(builder); | ||||
|         softLineBreak(builder); | ||||
|         hardLineBreak(builder); | ||||
|         paragraph(builder); | ||||
|         image(builder); | ||||
|         link(builder); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void beforeSetText(@NonNull TextView textView, @NonNull SpannableBuilder builder) { | ||||
|         OrderedListItemSpan.measure(textView, builder); | ||||
|     public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) { | ||||
|         OrderedListItemSpan.measure(textView, markdown); | ||||
|     } | ||||
| 
 | ||||
|     protected void text(@NonNull MarkwonVisitor.Builder builder) { | ||||
| @ -65,7 +97,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull StrongEmphasis strongEmphasis) { | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.visitChildren(strongEmphasis); | ||||
|                 visitor.setSpans(length, visitor.configuration().factory().strongEmphasis()); | ||||
|                 visitor.setSpans(length, visitor.factory().strongEmphasis()); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @ -76,7 +108,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Emphasis emphasis) { | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.visitChildren(emphasis); | ||||
|                 visitor.setSpans(length, visitor.configuration().factory().emphasis()); | ||||
|                 visitor.setSpans(length, visitor.factory().emphasis()); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @ -95,7 +127,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.incrementBlockQuoteIndent(); | ||||
|                 visitor.visitChildren(blockQuote); | ||||
|                 visitor.setSpans(length, visitor.configuration().factory().blockQuote(visitor.theme())); | ||||
|                 visitor.setSpans(length, visitor.factory().blockQuote(visitor.theme())); | ||||
|                 visitor.decrementBlockQuoteIndent(); | ||||
| 
 | ||||
|                 if (visitor.hasNext(blockQuote)) { | ||||
| @ -122,7 +154,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|                         .append(code.getLiteral()) | ||||
|                         .append('\u00a0'); | ||||
| 
 | ||||
|                 visitor.setSpans(length, visitor.configuration().factory().code(visitor.theme(), false)); | ||||
|                 visitor.setSpans(length, visitor.factory().code(visitor.theme(), false)); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @ -163,7 +195,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|         visitor.builder().append('\u00a0'); | ||||
| 
 | ||||
|         visitor.setSpans(length, visitor.configuration().factory().code(visitor.theme(), true)); | ||||
|         visitor.setSpans(length, visitor.factory().code(visitor.theme(), true)); | ||||
| 
 | ||||
|         if (visitor.hasNext(node)) { | ||||
|             visitor.ensureNewLine(); | ||||
| @ -220,7 +252,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|                     final int start = ((OrderedList) parent).getStartNumber(); | ||||
| 
 | ||||
|                     visitor.visitChildren(listItem); | ||||
|                     visitor.setSpans(length, visitor.configuration().factory().orderedListItem(visitor.theme(), start)); | ||||
|                     visitor.setSpans(length, visitor.factory().orderedListItem(visitor.theme(), start)); | ||||
| 
 | ||||
| 
 | ||||
|                     // after we have visited the children increment start number | ||||
| @ -230,7 +262,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|                 } else { | ||||
| 
 | ||||
|                     visitor.visitChildren(listItem); | ||||
|                     visitor.setSpans(length, visitor.configuration().factory().bulletListItem(visitor.theme(), visitor.listLevel() - 1)); | ||||
|                     visitor.setSpans(length, visitor.factory().bulletListItem(visitor.theme(), visitor.listLevel() - 1)); | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
| @ -256,7 +288,7 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|                 // without space it won't render | ||||
|                 visitor.builder().append('\u00a0'); | ||||
| 
 | ||||
|                 visitor.setSpans(length, visitor.configuration().factory().thematicBreak(visitor.theme())); | ||||
|                 visitor.setSpans(length, visitor.factory().thematicBreak(visitor.theme())); | ||||
| 
 | ||||
|                 if (visitor.hasNext(thematicBreak)) { | ||||
|                     visitor.ensureNewLine(); | ||||
| @ -265,4 +297,132 @@ public class CorePlugin extends AbstractMarkwonPlugin { | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected void heading(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(Heading.class, new MarkwonVisitor.NodeVisitor<Heading>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Heading heading) { | ||||
| 
 | ||||
|                 visitor.ensureNewLine(); | ||||
| 
 | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.visitChildren(heading); | ||||
|                 visitor.setSpans(length, visitor.factory().heading(visitor.theme(), heading.getLevel())); | ||||
| 
 | ||||
|                 if (visitor.hasNext(heading)) { | ||||
|                     visitor.ensureNewLine(); | ||||
|                     visitor.forceNewLine(); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected 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(' '); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected void hardLineBreak(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(HardLineBreak.class, new MarkwonVisitor.NodeVisitor<HardLineBreak>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull HardLineBreak hardLineBreak) { | ||||
|                 visitor.ensureNewLine(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected void paragraph(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(Paragraph.class, new MarkwonVisitor.NodeVisitor<Paragraph>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Paragraph paragraph) { | ||||
| 
 | ||||
|                 final boolean inTightList = isInTightList(paragraph); | ||||
| 
 | ||||
|                 if (!inTightList) { | ||||
|                     visitor.ensureNewLine(); | ||||
|                 } | ||||
| 
 | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.visitChildren(paragraph); | ||||
| 
 | ||||
|                 // @since 1.1.1 apply paragraph span | ||||
|                 visitor.setSpans(length, visitor.factory().paragraph(inTightList)); | ||||
| 
 | ||||
|                 if (!inTightList && visitor.hasNext(paragraph)) { | ||||
|                     visitor.ensureNewLine(); | ||||
|                     if (visitor.blockQuoteIndent() == 0) { | ||||
|                         visitor.forceNewLine(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected void image(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(Image.class, new MarkwonVisitor.NodeVisitor<Image>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Image image) { | ||||
| 
 | ||||
|                 final int length = visitor.length(); | ||||
| 
 | ||||
|                 visitor.visitChildren(image); | ||||
| 
 | ||||
|                 // we must check if anything _was_ added, as we need at least one char to render | ||||
|                 if (length == visitor.length()) { | ||||
|                     visitor.builder().append('\uFFFC'); | ||||
|                 } | ||||
| 
 | ||||
|                 final MarkwonConfiguration configuration = visitor.configuration(); | ||||
| 
 | ||||
|                 final Node parent = image.getParent(); | ||||
|                 final boolean link = parent instanceof Link; | ||||
|                 final String destination = configuration | ||||
|                         .urlProcessor() | ||||
|                         .process(image.getDestination()); | ||||
| 
 | ||||
|                 final Object spans = visitor.factory().image( | ||||
|                         visitor.theme(), | ||||
|                         destination, | ||||
|                         configuration.asyncDrawableLoader(), | ||||
|                         configuration.imageSizeResolver(), | ||||
|                         null, | ||||
|                         link); | ||||
| 
 | ||||
|                 visitor.setSpans(length, spans); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     protected void link(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(Link.class, new MarkwonVisitor.NodeVisitor<Link>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull Link link) { | ||||
|                 final int length = visitor.length(); | ||||
|                 visitor.visitChildren(link); | ||||
|                 final MarkwonConfiguration configuration = visitor.configuration(); | ||||
|                 final String destination = configuration.urlProcessor().process(link.getDestination()); | ||||
|                 visitor.setSpans(length, visitor.factory().link(visitor.theme(), destination, configuration.linkResolver())); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private static boolean isInTightList(@NonNull Paragraph paragraph) { | ||||
|         final Node parent = paragraph.getParent(); | ||||
|         if (parent != null) { | ||||
|             final Node gramps = parent.getParent(); | ||||
|             if (gramps instanceof ListBlock) { | ||||
|                 ListBlock list = (ListBlock) gramps; | ||||
|                 return list.isTight(); | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -20,8 +20,8 @@ public class OrderedListItemSpan implements LeadingMarginSpan { | ||||
|      * NB, this method must be called <em>before</em> setting text to a TextView (`TextView#setText` | ||||
|      * internally can trigger new Layout creation which will ask for leading margins right away) | ||||
|      * | ||||
|      * @param textView to which markdown will be applied | ||||
|      * @param text     parsed markdown to process | ||||
|      * @param textView to which toMarkdown will be applied | ||||
|      * @param text     parsed toMarkdown to process | ||||
|      * @since 2.0.1 | ||||
|      */ | ||||
|     public static void measure(@NonNull TextView textView, @NonNull CharSequence text) { | ||||
|  | ||||
| @ -4,6 +4,7 @@ import android.text.Spanned; | ||||
| 
 | ||||
| public abstract class LeadingMarginUtils { | ||||
| 
 | ||||
|     @SuppressWarnings("BooleanMethodIsAlwaysInverted") | ||||
|     public static boolean selfStart(int start, CharSequence text, Object span) { | ||||
|         return text instanceof Spanned && ((Spanned) text).getSpanStart(span) == start; | ||||
|     } | ||||
|  | ||||
| @ -47,7 +47,7 @@ public class MainActivity extends Activity { | ||||
| 
 | ||||
|         final SpannableBuilder builder = new SpannableBuilder(); | ||||
| 
 | ||||
|         // please note that here I am passing `0` as fallback it means that if markdown references | ||||
|         // please note that here I am passing `0` as fallback it means that if toMarkdown references | ||||
|         // unknown icon, it will try to load fallback one and will fail with ResourceNotFound. It's | ||||
|         // better to provide a valid fallback option | ||||
|         final IconSpanProvider spanProvider = IconSpanProvider.create(this, 0); | ||||
| @ -59,7 +59,7 @@ public class MainActivity extends Activity { | ||||
|                         .headingTextSizeMultipliers(textSizeMultipliers) | ||||
|                         .build()) | ||||
|                 .build(); | ||||
|         // create an instance of visitor to process parsed markdown | ||||
|         // create an instance of visitor to process parsed toMarkdown | ||||
|         final IconVisitor visitor = new IconVisitor( | ||||
|                 configuration, | ||||
|                 builder, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov