Add simple-ext module
This commit is contained in:
		
							parent
							
								
									fdb0f76e13
								
							
						
					
					
						commit
						a082e9ed44
					
				
							
								
								
									
										27
									
								
								markwon-simple-ext/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								markwon-simple-ext/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| apply plugin: 'com.android.library' | ||||
| 
 | ||||
| android { | ||||
| 
 | ||||
|     compileSdkVersion config['compile-sdk'] | ||||
|     buildToolsVersion config['build-tools'] | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion config['min-sdk'] | ||||
|         targetSdkVersion config['target-sdk'] | ||||
|         versionCode 1 | ||||
|         versionName version | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
| 
 | ||||
|     api project(':markwon-core') | ||||
| 
 | ||||
|     deps['test'].with { | ||||
|         testImplementation it['junit'] | ||||
|         testImplementation it['robolectric'] | ||||
|         testImplementation it['mockito'] | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| registerArtifact(this) | ||||
							
								
								
									
										4
									
								
								markwon-simple-ext/gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								markwon-simple-ext/gradle.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| POM_NAME=Simple Extension | ||||
| POM_ARTIFACT_ID=simple-ext | ||||
| POM_DESCRIPTION=Custom extension based on simple delimiter usage | ||||
| POM_PACKAGING=aar | ||||
							
								
								
									
										1
									
								
								markwon-simple-ext/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								markwon-simple-ext/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <manifest package="io.noties.markwon.simple.ext" /> | ||||
| @ -0,0 +1,64 @@ | ||||
| package io.noties.markwon.simple.ext; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.commonmark.parser.delimiter.DelimiterProcessor; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import io.noties.markwon.SpanFactory; | ||||
| 
 | ||||
| // @since 4.0.0-SNAPSHOT | ||||
| class SimpleExtBuilder { | ||||
| 
 | ||||
|     private final List<DelimiterProcessor> extensions = new ArrayList<>(2); | ||||
| 
 | ||||
|     private boolean isBuilt; | ||||
| 
 | ||||
|     void addExtension( | ||||
|             int length, | ||||
|             char character, | ||||
|             @NonNull SpanFactory spanFactory) { | ||||
| 
 | ||||
|         checkState(); | ||||
| 
 | ||||
|         extensions.add(new SimpleExtDelimiterProcessor( | ||||
|                 character, | ||||
|                 character, | ||||
|                 length, | ||||
|                 spanFactory)); | ||||
|     } | ||||
| 
 | ||||
|     void addExtension( | ||||
|             int length, | ||||
|             char openingCharacter, | ||||
|             char closingCharacter, | ||||
|             @NonNull SpanFactory spanFactory) { | ||||
| 
 | ||||
|         checkState(); | ||||
| 
 | ||||
|         extensions.add(new SimpleExtDelimiterProcessor( | ||||
|                 openingCharacter, | ||||
|                 closingCharacter, | ||||
|                 length, | ||||
|                 spanFactory)); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     List<DelimiterProcessor> build() { | ||||
| 
 | ||||
|         checkState(); | ||||
| 
 | ||||
|         isBuilt = true; | ||||
| 
 | ||||
|         return extensions; | ||||
|     } | ||||
| 
 | ||||
|     private void checkState() { | ||||
|         if (isBuilt) { | ||||
|             throw new IllegalStateException("SimpleExtBuilder is already built, " + | ||||
|                     "do not mutate SimpleExtPlugin after configuration is finished"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,70 @@ | ||||
| package io.noties.markwon.simple.ext; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.commonmark.node.Node; | ||||
| import org.commonmark.node.Text; | ||||
| import org.commonmark.parser.delimiter.DelimiterProcessor; | ||||
| import org.commonmark.parser.delimiter.DelimiterRun; | ||||
| 
 | ||||
| import io.noties.markwon.SpanFactory; | ||||
| 
 | ||||
| // @since 4.0.0-SNAPSHOT | ||||
| class SimpleExtDelimiterProcessor implements DelimiterProcessor { | ||||
| 
 | ||||
|     private final char open; | ||||
|     private final char close; | ||||
|     private final int length; | ||||
|     private final SpanFactory spanFactory; | ||||
| 
 | ||||
|     SimpleExtDelimiterProcessor( | ||||
|             char open, | ||||
|             char close, | ||||
|             int length, | ||||
|             @NonNull SpanFactory spanFactory) { | ||||
|         this.open = open; | ||||
|         this.close = close; | ||||
|         this.length = length; | ||||
|         this.spanFactory = spanFactory; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public char getOpeningCharacter() { | ||||
|         return open; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public char getClosingCharacter() { | ||||
|         return close; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int getMinLength() { | ||||
|         return length; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { | ||||
|         if (opener.length() >= length && closer.length() >= length) { | ||||
|             return length; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void process(Text opener, Text closer, int delimiterUse) { | ||||
| 
 | ||||
|         final Node node = new SimpleExtNode(spanFactory); | ||||
| 
 | ||||
|         Node tmp = opener.getNext(); | ||||
|         Node next; | ||||
| 
 | ||||
|         while (tmp != null && tmp != closer) { | ||||
|             next = tmp.getNext(); | ||||
|             node.appendChild(tmp); | ||||
|             tmp = next; | ||||
|         } | ||||
| 
 | ||||
|         opener.insertAfter(node); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package io.noties.markwon.simple.ext; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.commonmark.node.CustomNode; | ||||
| import org.commonmark.node.Visitor; | ||||
| 
 | ||||
| import io.noties.markwon.SpanFactory; | ||||
| 
 | ||||
| // @since 4.0.0-SNAPSHOT | ||||
| class SimpleExtNode extends CustomNode { | ||||
| 
 | ||||
|     private final SpanFactory spanFactory; | ||||
| 
 | ||||
|     SimpleExtNode(@NonNull SpanFactory spanFactory) { | ||||
|         this.spanFactory = spanFactory; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void accept(Visitor visitor) { | ||||
|         visitor.visit(this); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     SpanFactory spanFactory() { | ||||
|         return spanFactory; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,85 @@ | ||||
| package io.noties.markwon.simple.ext; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.commonmark.parser.Parser; | ||||
| import org.commonmark.parser.delimiter.DelimiterProcessor; | ||||
| 
 | ||||
| import io.noties.markwon.AbstractMarkwonPlugin; | ||||
| import io.noties.markwon.MarkwonVisitor; | ||||
| import io.noties.markwon.SpanFactory; | ||||
| import io.noties.markwon.SpannableBuilder; | ||||
| 
 | ||||
| /** | ||||
|  * @since 4.0.0-SNAPSHOT | ||||
|  */ | ||||
| public class SimpleExtPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     public interface SimpleExtConfigure { | ||||
|         void configure(@NonNull SimpleExtPlugin plugin); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static SimpleExtPlugin create() { | ||||
|         return new SimpleExtPlugin(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static SimpleExtPlugin create(@NonNull SimpleExtConfigure configure) { | ||||
|         final SimpleExtPlugin plugin = new SimpleExtPlugin(); | ||||
|         configure.configure(plugin); | ||||
|         return plugin; | ||||
|     } | ||||
| 
 | ||||
|     private final SimpleExtBuilder builder = new SimpleExtBuilder(); | ||||
| 
 | ||||
|     @SuppressWarnings("WeakerAccess") | ||||
|     SimpleExtPlugin() { | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public SimpleExtPlugin addExtension( | ||||
|             int length, | ||||
|             char character, | ||||
|             @NonNull SpanFactory spanFactory) { | ||||
|         builder.addExtension(length, character, spanFactory); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public SimpleExtPlugin addExtension( | ||||
|             int length, | ||||
|             char openingCharacter, | ||||
|             char closingCharacter, | ||||
|             @NonNull SpanFactory spanFactory) { | ||||
|         builder.addExtension(length, openingCharacter, closingCharacter, spanFactory); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureParser(@NonNull Parser.Builder builder) { | ||||
|         for (DelimiterProcessor processor : this.builder.build()) { | ||||
|             builder.customDelimiterProcessor(processor); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(SimpleExtNode.class, new MarkwonVisitor.NodeVisitor<SimpleExtNode>() { | ||||
|             @Override | ||||
|             public void visit(@NonNull MarkwonVisitor visitor, @NonNull SimpleExtNode simpleExtNode) { | ||||
| 
 | ||||
|                 final int length = visitor.length(); | ||||
| 
 | ||||
|                 visitor.visitChildren(simpleExtNode); | ||||
| 
 | ||||
|                 SpannableBuilder.setSpans( | ||||
|                         visitor.builder(), | ||||
|                         simpleExtNode.spanFactory().getSpans(visitor.configuration(), visitor.renderProps()), | ||||
|                         length, | ||||
|                         visitor.length() | ||||
|                 ); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -43,6 +43,7 @@ dependencies { | ||||
|     implementation project(':markwon-syntax-highlight') | ||||
|     implementation project(':markwon-recycler') | ||||
|     implementation project(':markwon-recycler-table') | ||||
|     implementation project(':markwon-simple-ext') | ||||
| 
 | ||||
|     implementation project(':markwon-image-picasso') | ||||
| 
 | ||||
|  | ||||
| @ -25,6 +25,7 @@ | ||||
|         <activity android:name="io.noties.markwon.sample.recycler.RecyclerActivity" /> | ||||
|         <activity android:name="io.noties.markwon.sample.theme.ThemeActivity" /> | ||||
|         <activity android:name=".html.HtmlActivity" /> | ||||
|         <activity android:name=".simpleext.SimpleExtActivity" /> | ||||
| 
 | ||||
|     </application> | ||||
| 
 | ||||
|  | ||||
| @ -24,6 +24,7 @@ import io.noties.markwon.sample.customextension.CustomExtensionActivity; | ||||
| import io.noties.markwon.sample.html.HtmlActivity; | ||||
| import io.noties.markwon.sample.latex.LatexActivity; | ||||
| import io.noties.markwon.sample.recycler.RecyclerActivity; | ||||
| import io.noties.markwon.sample.simpleext.SimpleExtActivity; | ||||
| 
 | ||||
| public class MainActivity extends Activity { | ||||
| 
 | ||||
| @ -102,6 +103,10 @@ public class MainActivity extends Activity { | ||||
|                 activity = HtmlActivity.class; | ||||
|                 break; | ||||
| 
 | ||||
|             case SIMPLE_EXT: | ||||
|                 activity = SimpleExtActivity.class; | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 throw new IllegalStateException("No Activity is associated with sample-item: " + item); | ||||
|         } | ||||
|  | ||||
| @ -15,7 +15,9 @@ public enum Sample { | ||||
| 
 | ||||
|     RECYCLER(R.string.sample_recycler), | ||||
| 
 | ||||
|     HTML(R.string.sample_html); | ||||
|     HTML(R.string.sample_html), | ||||
| 
 | ||||
|     SIMPLE_EXT(R.string.sample_simple_ext); | ||||
| 
 | ||||
|     private final int textResId; | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,43 @@ | ||||
| package io.noties.markwon.sample.simpleext; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.graphics.Color; | ||||
| import android.os.Bundle; | ||||
| import android.text.style.ForegroundColorSpan; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.Nullable; | ||||
| 
 | ||||
| import io.noties.markwon.Markwon; | ||||
| import io.noties.markwon.core.spans.EmphasisSpan; | ||||
| import io.noties.markwon.core.spans.StrongEmphasisSpan; | ||||
| import io.noties.markwon.sample.R; | ||||
| import io.noties.markwon.simple.ext.SimpleExtPlugin; | ||||
| 
 | ||||
| public class SimpleExtActivity extends Activity { | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
| 
 | ||||
|         setContentView(R.layout.activity_text_view); | ||||
| 
 | ||||
|         final TextView textView = findViewById(R.id.text_view); | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(SimpleExtPlugin.create(plugin -> plugin | ||||
|                         // +sometext+ | ||||
|                         .addExtension(1, '+', (_1, _2) -> new EmphasisSpan()) | ||||
|                         // ??sometext?? | ||||
|                         .addExtension(2, '?', (_1, _2) -> new StrongEmphasisSpan()) | ||||
|                         // @@sometext$$ | ||||
|                         .addExtension(2, '@', '$', (_1, _2) -> new ForegroundColorSpan(Color.RED)))) | ||||
|                 .build(); | ||||
| 
 | ||||
|         final String markdown = "# SimpleExt\n" + | ||||
|                 "\n" + | ||||
|                 "+let's start with `+`, ??then we can use this, and finally @@this$$??+"; | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, markdown); | ||||
|     } | ||||
| } | ||||
| @ -17,4 +17,7 @@ | ||||
| 
 | ||||
|     <string name="sample_html"># \# Html\n\nShows how to define own tag handlers</string> | ||||
| 
 | ||||
|     <string name="sample_simple_ext"># \# SimpleExt\n\nShows how to use SimpleExtPlugin module | ||||
|         to create own delimited parser extensions</string> | ||||
| 
 | ||||
| </resources> | ||||
| @ -12,5 +12,6 @@ include ':app', ':sample', | ||||
|         ':markwon-linkify', | ||||
|         ':markwon-recycler', | ||||
|         ':markwon-recycler-table', | ||||
|         ':markwon-simple-ext', | ||||
|         ':markwon-syntax-highlight', | ||||
|         ':markwon-test-span' | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov