Add simple-ext module

This commit is contained in:
Dimitry Ivanov 2019-06-24 14:35:50 +03:00
parent fdb0f76e13
commit a082e9ed44
14 changed files with 336 additions and 1 deletions

@ -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)

@ -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

@ -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'