Add markwon-ext-latex module extension
This commit is contained in:
parent
6a82b75aba
commit
577c3fc782
@ -61,6 +61,7 @@ ext {
|
||||
'commonmark-table' : "com.atlassian.commonmark:commonmark-ext-gfm-tables:$commonMarkVersion",
|
||||
'android-svg' : 'com.caverock:androidsvg:1.2.1',
|
||||
'android-gif' : 'pl.droidsonroids.gif:android-gif-drawable:1.2.14',
|
||||
'jlatexmath-android' : 'ru.noties:jlatexmath-android:0.1.0',
|
||||
'okhttp' : 'com.squareup.okhttp3:okhttp:3.9.0',
|
||||
'prism4j' : 'ru.noties:prism4j:1.1.0',
|
||||
'debug' : 'ru.noties:debug:3.0.0@jar',
|
||||
|
22
markwon-ext-latex/build.gradle
Normal file
22
markwon-ext-latex/build.gradle
Normal file
@ -0,0 +1,22 @@
|
||||
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')
|
||||
api deps['jlatexmath-android']
|
||||
}
|
||||
|
||||
registerArtifact(this)
|
1
markwon-ext-latex/src/main/AndroidManifest.xml
Normal file
1
markwon-ext-latex/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
||||
<manifest package="ru.noties.markwon.ext.latex" />
|
@ -1,4 +1,4 @@
|
||||
package ru.noties.markwon.sample.jlatexmath;
|
||||
package ru.noties.markwon.ext.latex;
|
||||
|
||||
import org.commonmark.node.CustomBlock;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ru.noties.markwon.sample.jlatexmath;
|
||||
package ru.noties.markwon.ext.latex;
|
||||
|
||||
import org.commonmark.node.Block;
|
||||
import org.commonmark.parser.block.AbstractBlockParser;
|
@ -0,0 +1,143 @@
|
||||
package ru.noties.markwon.ext.latex;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.commonmark.parser.Parser;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import ru.noties.jlatexmath.JLatexMathDrawable;
|
||||
import ru.noties.markwon.AbstractMarkwonPlugin;
|
||||
import ru.noties.markwon.MarkwonConfiguration;
|
||||
import ru.noties.markwon.MarkwonVisitor;
|
||||
import ru.noties.markwon.image.AsyncDrawableLoader;
|
||||
import ru.noties.markwon.image.ImageItem;
|
||||
import ru.noties.markwon.image.ImageSize;
|
||||
import ru.noties.markwon.image.MediaDecoder;
|
||||
import ru.noties.markwon.image.SchemeHandler;
|
||||
|
||||
public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
||||
|
||||
@NonNull
|
||||
public static JLatexMathPlugin create(@NonNull Config config) {
|
||||
return new JLatexMathPlugin(config);
|
||||
}
|
||||
|
||||
public static class Config {
|
||||
|
||||
protected final float textSize;
|
||||
|
||||
protected Drawable background;
|
||||
|
||||
@JLatexMathDrawable.Align
|
||||
protected int align = JLatexMathDrawable.ALIGN_CENTER;
|
||||
|
||||
protected boolean fitCanvas = true;
|
||||
|
||||
protected int padding;
|
||||
|
||||
public Config(float textSize) {
|
||||
this.textSize = textSize;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String makeDestination(@NonNull String latex) {
|
||||
return SCHEME + "://" + latex;
|
||||
}
|
||||
|
||||
private static final String SCHEME = "jlatexmath";
|
||||
private static final String CONTENT_TYPE = "text/jlatexmath";
|
||||
|
||||
private final Config config;
|
||||
|
||||
JLatexMathPlugin(@NonNull Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureParser(@NonNull Parser.Builder builder) {
|
||||
builder.customBlockParserFactory(new JLatexMathBlockParser.Factory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(JLatexMathBlock.class, new MarkwonVisitor.NodeVisitor<JLatexMathBlock>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull JLatexMathBlock jLatexMathBlock) {
|
||||
|
||||
final String latex = jLatexMathBlock.latex();
|
||||
|
||||
final int length = visitor.length();
|
||||
visitor.builder().append(latex);
|
||||
|
||||
final MarkwonConfiguration configuration = visitor.configuration();
|
||||
|
||||
visitor.setSpans(
|
||||
length,
|
||||
configuration.factory().image(
|
||||
visitor.theme(),
|
||||
makeDestination(latex),
|
||||
configuration.asyncDrawableLoader(),
|
||||
configuration.imageSizeResolver(),
|
||||
new ImageSize(new ImageSize.Dimension(100, "%"), null),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
|
||||
builder
|
||||
.addSchemeHandler(SCHEME, new SchemeHandler() {
|
||||
@Nullable
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
ImageItem item = null;
|
||||
|
||||
try {
|
||||
final byte[] bytes = raw.substring(SCHEME.length()).getBytes("UTF-8");
|
||||
item = new ImageItem(
|
||||
CONTENT_TYPE,
|
||||
new ByteArrayInputStream(bytes));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
})
|
||||
.addMediaDecoder(CONTENT_TYPE, new MediaDecoder() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable decode(@NonNull InputStream inputStream) {
|
||||
|
||||
final Scanner scanner = new Scanner(inputStream, "UTF-8").useDelimiter("\\A");
|
||||
final String latex = scanner.hasNext()
|
||||
? scanner.next()
|
||||
: null;
|
||||
|
||||
if (latex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JLatexMathDrawable.builder(latex)
|
||||
.textSize(config.textSize)
|
||||
.background(config.background)
|
||||
.align(config.align)
|
||||
.fitCanvas(config.fitCanvas)
|
||||
.padding(config.padding)
|
||||
.build();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -79,12 +79,6 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
@Override
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
OrderedListItemSpan.measure(textView, markdown);
|
||||
AsyncDrawableScheduler.unschedule(textView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSetText(@NonNull TextView textView) {
|
||||
AsyncDrawableScheduler.schedule(textView);
|
||||
}
|
||||
|
||||
protected void text(@NonNull MarkwonVisitor.Builder builder) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ru.noties.markwon.core;
|
||||
package ru.noties.markwon.image;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@ -15,12 +15,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import ru.noties.markwon.renderer.R;
|
||||
import ru.noties.markwon.image.AsyncDrawable;
|
||||
import ru.noties.markwon.spans.AsyncDrawableSpan;
|
||||
|
||||
abstract class AsyncDrawableScheduler {
|
||||
public abstract class AsyncDrawableScheduler {
|
||||
|
||||
static void schedule(@NonNull final TextView textView) {
|
||||
public static void schedule(@NonNull final TextView textView) {
|
||||
|
||||
final List<AsyncDrawable> list = extract(textView);
|
||||
if (list.size() > 0) {
|
||||
@ -50,7 +49,7 @@ abstract class AsyncDrawableScheduler {
|
||||
}
|
||||
|
||||
// must be called when text manually changed in TextView
|
||||
static void unschedule(@NonNull TextView view) {
|
||||
public static void unschedule(@NonNull TextView view) {
|
||||
for (AsyncDrawable drawable : extract(view)) {
|
||||
drawable.setCallback2(null);
|
||||
}
|
@ -2,6 +2,7 @@ package ru.noties.markwon.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.Image;
|
||||
import org.commonmark.node.Link;
|
||||
@ -89,4 +90,14 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeSetText(@NonNull TextView textView, @NonNull CharSequence markdown) {
|
||||
AsyncDrawableScheduler.unschedule(textView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSetText(@NonNull TextView textView) {
|
||||
AsyncDrawableScheduler.schedule(textView);
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation project(':markwon')
|
||||
implementation project(':markwon-ext-latex')
|
||||
// implementation project(':markwon-image-loader')
|
||||
implementation 'ru.noties:jlatexmath-android:0.1.0'
|
||||
// implementation 'ru.noties:jlatexmath-android:0.1.0'
|
||||
}
|
||||
|
@ -1,138 +0,0 @@
|
||||
package ru.noties.markwon.sample.jlatexmath;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Scanner;
|
||||
|
||||
import ru.noties.jlatexmath.JLatexMathDrawable;
|
||||
import ru.noties.markwon.il.ImageItem;
|
||||
import ru.noties.markwon.il.MediaDecoder;
|
||||
import ru.noties.markwon.il.SchemeHandler;
|
||||
|
||||
public class JLatexMathMedia {
|
||||
|
||||
public static class Config {
|
||||
|
||||
protected final float textSize;
|
||||
|
||||
protected Drawable background;
|
||||
|
||||
@JLatexMathDrawable.Align
|
||||
protected int align = JLatexMathDrawable.ALIGN_CENTER;
|
||||
|
||||
protected boolean fitCanvas = true;
|
||||
|
||||
protected int padding;
|
||||
|
||||
public Config(float textSize) {
|
||||
this.textSize = textSize;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String makeDestination(@NonNull String latex) {
|
||||
return SCHEME + "://" + latex;
|
||||
}
|
||||
|
||||
private static final String SCHEME = "jlatexmath";
|
||||
private static final String CONTENT_TYPE = "text/jlatexmath";
|
||||
|
||||
private final Config config;
|
||||
|
||||
public JLatexMathMedia(@NonNull Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public SchemeHandler schemeHandler() {
|
||||
return new SchemeHandlerImpl();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public MediaDecoder mediaDecoder() {
|
||||
return new MediaDecoderImpl(config);
|
||||
}
|
||||
|
||||
static class SchemeHandlerImpl extends SchemeHandler {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
ImageItem item = null;
|
||||
|
||||
try {
|
||||
final byte[] bytes = raw.substring(SCHEME.length()).getBytes("UTF-8");
|
||||
item = new ImageItem(
|
||||
CONTENT_TYPE,
|
||||
new ByteArrayInputStream(bytes),
|
||||
null
|
||||
);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NonNull String raw) {
|
||||
// no op
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Collection<String> schemes() {
|
||||
return Collections.singleton(SCHEME);
|
||||
}
|
||||
}
|
||||
|
||||
static class MediaDecoderImpl extends MediaDecoder {
|
||||
|
||||
private final Config config;
|
||||
|
||||
MediaDecoderImpl(@NonNull Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDecodeByContentType(@Nullable String contentType) {
|
||||
return CONTENT_TYPE.equals(contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDecodeByFileName(@NonNull String fileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable decode(@NonNull InputStream inputStream) {
|
||||
|
||||
final Scanner scanner = new Scanner(inputStream, "UTF-8").useDelimiter("\\A");
|
||||
final String latex = scanner.hasNext()
|
||||
? scanner.next()
|
||||
: null;
|
||||
|
||||
if (latex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JLatexMathDrawable.builder(latex)
|
||||
.textSize(config.textSize)
|
||||
.background(config.background)
|
||||
.align(config.align)
|
||||
.fitCanvas(config.fitCanvas)
|
||||
.padding(config.padding)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,17 +4,10 @@ import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.CustomBlock;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
|
||||
import ru.noties.jlatexmath.JLatexMathAndroid;
|
||||
import ru.noties.markwon.Markwon;
|
||||
import ru.noties.markwon.MarkwonConfiguration;
|
||||
import ru.noties.markwon.SpannableBuilder;
|
||||
import ru.noties.markwon.il.AsyncDrawableLoader;
|
||||
import ru.noties.markwon.image.ImageSize;
|
||||
import ru.noties.markwon.renderer.SpannableMarkdownVisitor;
|
||||
import ru.noties.markwon.core.CorePlugin;
|
||||
import ru.noties.markwon.ext.latex.JLatexMathPlugin;
|
||||
import ru.noties.markwon.image.ImagesPlugin;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@ -45,61 +38,21 @@ public class MainActivity extends Activity {
|
||||
// latex += "\\end{array}";
|
||||
|
||||
|
||||
final JLatexMathMedia.Config config = new JLatexMathMedia.Config(textView.getTextSize()) {{
|
||||
final JLatexMathPlugin.Config config = new JLatexMathPlugin.Config(textView.getTextSize()) {{
|
||||
// align = JLatexMathDrawable.ALIGN_RIGHT;
|
||||
}};
|
||||
final JLatexMathMedia jLatexMathMedia = new JLatexMathMedia(config);
|
||||
|
||||
final AsyncDrawableLoader asyncDrawableLoader = AsyncDrawableLoader.builder()
|
||||
.addSchemeHandler(jLatexMathMedia.schemeHandler())
|
||||
.mediaDecoders(jLatexMathMedia.mediaDecoder())
|
||||
.build();
|
||||
|
||||
final MarkwonConfiguration configuration = MarkwonConfiguration.builder(this)
|
||||
.asyncDrawableLoader(asyncDrawableLoader)
|
||||
.build();
|
||||
|
||||
final String markdown = "# Example of LaTeX\n\n$$"
|
||||
+ latex + "$$\n\n something like **this**";
|
||||
|
||||
final Parser parser = new Parser.Builder()
|
||||
.customBlockParserFactory(new JLatexMathBlockParser.Factory())
|
||||
final Markwon markwon = Markwon.builder(this)
|
||||
.use(CorePlugin.create())
|
||||
// strictly speaking this one is not required as long as JLatexMathPlugin schedules
|
||||
// drawables on it's own
|
||||
.use(ImagesPlugin.create(this))
|
||||
.use(JLatexMathPlugin.create(config))
|
||||
.build();
|
||||
|
||||
final Node node = parser.parse(markdown);
|
||||
final SpannableBuilder builder = new SpannableBuilder();
|
||||
final SpannableMarkdownVisitor visitor = new SpannableMarkdownVisitor(MarkwonConfiguration.create(this), builder) {
|
||||
|
||||
@Override
|
||||
public void visit(CustomBlock customBlock) {
|
||||
|
||||
if (!(customBlock instanceof JLatexMathBlock)) {
|
||||
super.visit(customBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
final String latex = ((JLatexMathBlock) customBlock).latex();
|
||||
|
||||
final int length = builder.length();
|
||||
builder.append(latex);
|
||||
|
||||
SpannableBuilder.setSpans(
|
||||
builder,
|
||||
configuration.factory().image(
|
||||
configuration.theme(),
|
||||
JLatexMathMedia.makeDestination(latex),
|
||||
configuration.asyncDrawableLoader(),
|
||||
configuration.imageSizeResolver(),
|
||||
new ImageSize(new ImageSize.Dimension(100, "%"), null),
|
||||
false
|
||||
),
|
||||
length,
|
||||
builder.length()
|
||||
);
|
||||
}
|
||||
};
|
||||
node.accept(visitor);
|
||||
|
||||
Markwon.setText(textView, builder.text());
|
||||
markwon.setMarkdown(textView, markdown);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
rootProject.name = 'MarkwonProject'
|
||||
include ':app',
|
||||
':markwon',
|
||||
':markwon-ext-latex',
|
||||
':markwon-ext-strikethrough',
|
||||
':markwon-ext-tables',
|
||||
':markwon-ext-tasklist',
|
||||
|
Loading…
x
Reference in New Issue
Block a user