JLatexMathPlugin add error handling

This commit is contained in:
Dimitry Ivanov 2020-03-02 10:22:04 +03:00
parent c98f456744
commit a1f12641c3
3 changed files with 110 additions and 32 deletions

View File

@ -13,8 +13,12 @@
``` ```
* `JLatexMathPlugin`: add `theme` (to customize both inlines and blocks) * `JLatexMathPlugin`: add `theme` (to customize both inlines and blocks)
* `JLatexMathPlugin`: add `renderMode` to use previous (pre `4.3.0`) LaTeX rendering * `JLatexMathPlugin`: add `renderMode` to use previous (pre `4.3.0`) LaTeX rendering
* add `JLatexMathPlugin.ErrorHandler` to catch latex rendering errors and (optionally) display error drawable ([#204])
* add `SoftBreakAddsNewLinePlugin` plugin (`core` module) * add `SoftBreakAddsNewLinePlugin` plugin (`core` module)
* `LinkResolverDef` defaults to `https` when a link does not have scheme information * `LinkResolverDef` defaults to `https` when a link does not have scheme information ([#75])
[#75]: https://github.com/noties/Markwon/issues/75
[#204]: https://github.com/noties/Markwon/issues/204
# 4.2.2 # 4.2.2

View File

@ -29,6 +29,7 @@ import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.AsyncDrawableLoader; import io.noties.markwon.image.AsyncDrawableLoader;
import io.noties.markwon.image.AsyncDrawableScheduler; import io.noties.markwon.image.AsyncDrawableScheduler;
import io.noties.markwon.image.AsyncDrawableSpan; import io.noties.markwon.image.AsyncDrawableSpan;
import io.noties.markwon.image.DrawableUtils;
import io.noties.markwon.image.ImageSizeResolver; import io.noties.markwon.image.ImageSizeResolver;
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
import ru.noties.jlatexmath.JLatexMathDrawable; import ru.noties.jlatexmath.JLatexMathDrawable;
@ -62,6 +63,22 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
BLOCKS_AND_INLINES BLOCKS_AND_INLINES
} }
/**
* @since 4.3.0-SNAPSHOT
*/
public interface ErrorHandler {
/**
* @param latex that caused the error or null if operated `AsyncDrawable`
* is not an instance of `JLatexAsyncDrawable`
* @param error occurred
* @return (optional) error drawable that will be used instead (if drawable will have bounds
* it will be used, if not intrinsic bounds will be set)
*/
@Nullable
Drawable handleError(@Nullable String latex, @NonNull Throwable error);
}
public interface BuilderConfigure { public interface BuilderConfigure {
void configureBuilder(@NonNull Builder builder); void configureBuilder(@NonNull Builder builder);
} }
@ -125,11 +142,15 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
// @since 4.3.0-SNAPSHOT // @since 4.3.0-SNAPSHOT
private final RenderMode renderMode; private final RenderMode renderMode;
// @since 4.3.0-SNAPSHOT
private final ErrorHandler errorHandler;
private final ExecutorService executorService; private final ExecutorService executorService;
Config(@NonNull Builder builder) { Config(@NonNull Builder builder) {
this.theme = builder.theme.build(); this.theme = builder.theme.build();
this.renderMode = builder.renderMode; this.renderMode = builder.renderMode;
this.errorHandler = builder.errorHandler;
// @since 4.0.0 // @since 4.0.0
ExecutorService executorService = builder.executorService; ExecutorService executorService = builder.executorService;
if (executorService == null) { if (executorService == null) {
@ -284,6 +305,9 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
// @since 4.3.0-SNAPSHOT // @since 4.3.0-SNAPSHOT
private RenderMode renderMode = RenderMode.BLOCKS_AND_INLINES; private RenderMode renderMode = RenderMode.BLOCKS_AND_INLINES;
// @since 4.3.0-SNAPSHOT
private ErrorHandler errorHandler;
// @since 4.0.0 // @since 4.0.0
private ExecutorService executorService; private ExecutorService executorService;
@ -305,6 +329,12 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
return this; return this;
} }
@NonNull
public Builder errorHandler(@Nullable ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
return this;
}
/** /**
* @since 4.0.0 * @since 4.0.0
*/ */
@ -351,10 +381,24 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
try { try {
execute(); execute();
} catch (Throwable t) { } catch (Throwable t) {
// @since 4.3.0-SNAPSHOT add error handling
final ErrorHandler errorHandler = config.errorHandler;
if (errorHandler == null) {
// as before
Log.e( Log.e(
"JLatexMathPlugin", "JLatexMathPlugin",
"Error displaying latex: `" + drawable.getDestination() + "`", "Error displaying latex: `" + drawable.getDestination() + "`",
t); t);
} else {
final Drawable errorDrawable = errorHandler.handleError(
drawable.getDestination(),
t
);
if (errorDrawable != null) {
DrawableUtils.applyIntrinsicBoundsIfEmpty(errorDrawable);
setResult(drawable, errorDrawable);
}
}
} }
} }
@ -370,19 +414,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
jLatexMathDrawable = createInlineDrawable(jLatextAsyncDrawable.getDestination()); jLatexMathDrawable = createInlineDrawable(jLatextAsyncDrawable.getDestination());
} }
// we must post to handler, but also have a way to identify the drawable setResult(drawable, jLatexMathDrawable);
// for which we are posting (in case of cancellation)
handler.postAtTime(new Runnable() {
@Override
public void run() {
// remove entry from cache (it will be present if task is not cancelled)
if (cache.remove(drawable) != null
&& drawable.isAttached()) {
drawable.setResult(jLatexMathDrawable);
}
}
}, drawable, SystemClock.uptimeMillis());
} }
})); }));
} }
@ -456,6 +488,23 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
return builder.build(); return builder.build();
} }
// @since 4.3.0-SNAPSHOT
private void setResult(@NonNull final AsyncDrawable drawable, @NonNull final Drawable result) {
// we must post to handler, but also have a way to identify the drawable
// for which we are posting (in case of cancellation)
handler.postAtTime(new Runnable() {
@Override
public void run() {
// remove entry from cache (it will be present if task is not cancelled)
if (cache.remove(drawable) != null
&& drawable.isAttached()) {
drawable.setResult(result);
}
}
}, drawable, SystemClock.uptimeMillis());
}
} }
private static class InlineImageSizeResolver extends ImageSizeResolver { private static class InlineImageSizeResolver extends ImageSizeResolver {

View File

@ -2,12 +2,15 @@ package io.noties.markwon.sample.latex;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import io.noties.debug.Debug;
import io.noties.markwon.Markwon; import io.noties.markwon.Markwon;
import io.noties.markwon.ext.latex.JLatexMathPlugin; import io.noties.markwon.ext.latex.JLatexMathPlugin;
import io.noties.markwon.ext.latex.JLatexMathTheme; import io.noties.markwon.ext.latex.JLatexMathTheme;
@ -57,6 +60,7 @@ public class LatexActivity extends ActivityWithMenuOptions {
.add("bangle", this::bangle) .add("bangle", this::bangle)
.add("boxes", this::boxes) .add("boxes", this::boxes)
.add("insideBlockQuote", this::insideBlockQuote) .add("insideBlockQuote", this::insideBlockQuote)
.add("error", this::error)
.add("legacy", this::legacy); .add("legacy", this::legacy);
} }
@ -95,6 +99,27 @@ public class LatexActivity extends ActivityWithMenuOptions {
render(md); render(md);
} }
private void error() {
final String md = wrapLatexInSampleMarkdown("\\sum_{i=0}^\\infty x \\cdot 0 \\rightarrow \\iMightNotExist{0}");
final Markwon markwon = Markwon.builder(this)
.usePlugin(MarkwonInlineParserPlugin.create())
.usePlugin(JLatexMathPlugin.create(textView.getTextSize(), builder -> {
//noinspection Convert2Lambda
builder.errorHandler(new JLatexMathPlugin.ErrorHandler() {
@Nullable
@Override
public Drawable handleError(@Nullable String latex, @NonNull Throwable error) {
Debug.e(error, latex);
return ContextCompat.getDrawable(LatexActivity.this, R.drawable.ic_android_black_24dp);
}
});
}))
.build();
markwon.setMarkdown(textView, md);
}
private void legacy() { private void legacy() {
final String md = wrapLatexInSampleMarkdown(LATEX_BANGLE); final String md = wrapLatexInSampleMarkdown(LATEX_BANGLE);
@ -127,7 +152,7 @@ public class LatexActivity extends ActivityWithMenuOptions {
final float textSize = textView.getTextSize(); final float textSize = textView.getTextSize();
final Resources r = getResources(); final Resources r = getResources();
final Markwon markwon = Markwon.builder(this) final Markwon markwon = Markwon.builder(this)
// NB! `MarkwonInlineParserPlugin` is required in order to parse inlines // NB! `MarkwonInlineParserPlugin` is required in order to parse inlines
.usePlugin(MarkwonInlineParserPlugin.create()) .usePlugin(MarkwonInlineParserPlugin.create())
.usePlugin(JLatexMathPlugin.create(textSize, textSize * 1.25F, builder -> { .usePlugin(JLatexMathPlugin.create(textSize, textSize * 1.25F, builder -> {