diff --git a/build.gradle b/build.gradle index 6ba06545..f5ccc8a1 100644 --- a/build.gradle +++ b/build.gradle @@ -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', diff --git a/markwon-ext-latex/build.gradle b/markwon-ext-latex/build.gradle new file mode 100644 index 00000000..cd984c60 --- /dev/null +++ b/markwon-ext-latex/build.gradle @@ -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) \ No newline at end of file diff --git a/markwon-ext-latex/src/main/AndroidManifest.xml b/markwon-ext-latex/src/main/AndroidManifest.xml new file mode 100644 index 00000000..fee2db10 --- /dev/null +++ b/markwon-ext-latex/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlock.java b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlock.java similarity index 84% rename from sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlock.java rename to markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlock.java index 3e3e4479..d49d108a 100644 --- a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlock.java +++ b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlock.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.sample.jlatexmath; +package ru.noties.markwon.ext.latex; import org.commonmark.node.CustomBlock; diff --git a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlockParser.java b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlockParser.java similarity index 97% rename from sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlockParser.java rename to markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlockParser.java index 542b3869..7aac76f2 100644 --- a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathBlockParser.java +++ b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathBlockParser.java @@ -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; diff --git a/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathPlugin.java b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathPlugin.java new file mode 100644 index 00000000..eec628a9 --- /dev/null +++ b/markwon-ext-latex/src/main/java/ru/noties/markwon/ext/latex/JLatexMathPlugin.java @@ -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() { + @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(); + } + }); + } +} diff --git a/markwon/src/main/java/ru/noties/markwon/core/CorePlugin.java b/markwon/src/main/java/ru/noties/markwon/core/CorePlugin.java index 832536da..37a92f7c 100644 --- a/markwon/src/main/java/ru/noties/markwon/core/CorePlugin.java +++ b/markwon/src/main/java/ru/noties/markwon/core/CorePlugin.java @@ -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) { diff --git a/markwon/src/main/java/ru/noties/markwon/core/AsyncDrawableScheduler.java b/markwon/src/main/java/ru/noties/markwon/image/AsyncDrawableScheduler.java similarity index 95% rename from markwon/src/main/java/ru/noties/markwon/core/AsyncDrawableScheduler.java rename to markwon/src/main/java/ru/noties/markwon/image/AsyncDrawableScheduler.java index 3d7fae23..0de99c61 100644 --- a/markwon/src/main/java/ru/noties/markwon/core/AsyncDrawableScheduler.java +++ b/markwon/src/main/java/ru/noties/markwon/image/AsyncDrawableScheduler.java @@ -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 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); } diff --git a/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java b/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java index 0154eb8f..5f43ab54 100644 --- a/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java +++ b/markwon/src/main/java/ru/noties/markwon/image/ImagesPlugin.java @@ -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); + } } diff --git a/sample-latex-math/build.gradle b/sample-latex-math/build.gradle index f9f7c1eb..2633b03a 100644 --- a/sample-latex-math/build.gradle +++ b/sample-latex-math/build.gradle @@ -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' } diff --git a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathMedia.java b/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathMedia.java deleted file mode 100644 index bf0b76a5..00000000 --- a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/JLatexMathMedia.java +++ /dev/null @@ -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 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(); - } - } -} diff --git a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/MainActivity.java b/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/MainActivity.java index 5f2ea561..01fb2718 100644 --- a/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/MainActivity.java +++ b/sample-latex-math/src/main/java/ru/noties/markwon/sample/jlatexmath/MainActivity.java @@ -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); } } diff --git a/settings.gradle b/settings.gradle index 13fb6c63..10d8564b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name = 'MarkwonProject' include ':app', ':markwon', + ':markwon-ext-latex', ':markwon-ext-strikethrough', ':markwon-ext-tables', ':markwon-ext-tasklist',