Add simple-ext module
This commit is contained in:
parent
fdb0f76e13
commit
a082e9ed44
markwon-simple-ext
sample
settings.gradle
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");
|
||||
}
|
||||
}
|
||||
}
|
70
markwon-simple-ext/src/main/java/io/noties/markwon/simple/ext/SimpleExtDelimiterProcessor.java
Normal file
70
markwon-simple-ext/src/main/java/io/noties/markwon/simple/ext/SimpleExtDelimiterProcessor.java
Normal file
@ -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