Preparing 4.0.0 release
This commit is contained in:
parent
d65a1809ca
commit
386254f962
47
CHANGELOG.md
47
CHANGELOG.md
@ -1,9 +1,40 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
# 3.0.2
|
# 4.0.0
|
||||||
|
* maven group-id change to `io.noties.markwon` (was `ru.noties.markwon`)
|
||||||
|
* package name change to `io.notier.markwon.*` (was `ru.noties.markwon.*`)
|
||||||
|
* androidx artifacts (#76)
|
||||||
|
* `Markwon#builder` does not require explicit `CorePlugin` (added automatically),
|
||||||
|
use `Markwon#builderNoCore()` to obtain a builder without `CorePlugin`
|
||||||
|
* Removed `Priority` abstraction and `MarkwonPlugin#priority` (use `MarkwonPlugin.Registry`)
|
||||||
|
* Removed `MarkwonPlugin#configureHtmlRenderer` (for configuration use `HtmlPlugin` directly)
|
||||||
|
* Removed `MarkwonPlugin#configureImages` (for configuration use `ImagesPlugin` directly)
|
||||||
|
* Added `MarkwonPlugin.Registry` and `MarkwonPlugin#configure(Registry)` method
|
||||||
|
* `CorePlugin#addOnTextAddedListener` (process raw text added)
|
||||||
|
* `ImageSizeResolver` signature change (accept `AsyncDrawable`)
|
||||||
|
* `LinkResolver` is now an independent entity (previously part of `LinkSpan`)
|
||||||
|
* `AsyncDrawableScheduler` can now be called multiple times without performance penalty
|
||||||
|
* `AsyncDrawable` now exposes its destination, image-size, last known dimensions (canvas, text-size)
|
||||||
|
* `AsyncDrawableLoader` signature change (accept `AsyncDrawable`)
|
||||||
|
* Add `LastLineSpacingSpan`
|
||||||
|
* Add `MarkwonConfiguration.Builder#asyncDrawableLoader` method
|
||||||
|
* `ImagesPlugin` removed from `core` artifact
|
||||||
|
(also removed `images-gif`, `images-okhttp` and `images-svg` artifacts and their plugins)
|
||||||
|
* `ImagesPlugin` exposes configuration (adding scheme-handler, media-decoder, etc)
|
||||||
|
* `ImagesPlugin` allows multiple images with the same source (URL)
|
||||||
|
* Add `PlaceholderProvider` and `ErrorHandler` to `ImagesPlugin`
|
||||||
|
* `GIF` and `SVG` media-decoders are automatically added to `ImagesPlugin` if required libraries are found in the classpath
|
||||||
|
* `ImageItem` is now abstract, has 2 implementations: `withResult`, `withDecodingNeeded`
|
||||||
|
* Add `images-glide`, `images-picasso`, `linkify`, `simple-ext` modules
|
||||||
|
* `JLatexMathPlugin` is now independent of `ImagesPlugin`
|
||||||
|
* Fix wrong `JLatexMathPlugin` formulas sizes (#138)
|
||||||
|
* `JLatexMathPlugin` has `backgroundProvider`, `executorService` configuration
|
||||||
|
* `HtmlPlugin` is self-contained (all configuration is moved in the plugin itself)
|
||||||
|
|
||||||
|
## 3.0.2
|
||||||
* Fix `latex` plugin (#136)
|
* Fix `latex` plugin (#136)
|
||||||
* Add `#create(Call.Factory)` factory method to `OkHttpImagesPlugin` (#129)
|
* Add `#create(Call.Factory)` factory method to `OkHttpImagesPlugin` (#129)
|
||||||
thanks to @ZacSweers
|
<br>Thanks to @ZacSweers
|
||||||
|
|
||||||
## 3.0.1
|
## 3.0.1
|
||||||
* Add `AsyncDrawableLoader.Builder#implementation` method (#109)
|
* Add `AsyncDrawableLoader.Builder#implementation` method (#109)
|
||||||
@ -64,7 +95,7 @@ to get the full picture of latest changes.
|
|||||||
* Add SpannableBuilder#getSpans method
|
* Add SpannableBuilder#getSpans method
|
||||||
* Fix DataUri scheme handler in image-loader (#74)
|
* Fix DataUri scheme handler in image-loader (#74)
|
||||||
* Introduced a "copy" builder for SpannableThem
|
* Introduced a "copy" builder for SpannableThem
|
||||||
Thanks @c-b-h
|
<br>Thanks @c-b-h
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
* Add `html-parser-api` and `html-parser-impl` modules
|
* Add `html-parser-api` and `html-parser-impl` modules
|
||||||
@ -90,7 +121,7 @@ to get the full picture of latest changes.
|
|||||||
* Fix OrderedListItemSpan text position (baseline) (#55)
|
* Fix OrderedListItemSpan text position (baseline) (#55)
|
||||||
* Add softBreakAddsNewLine option for SpannableConfiguration (#54)
|
* Add softBreakAddsNewLine option for SpannableConfiguration (#54)
|
||||||
* Paragraph text can now explicitly be spanned (#58)
|
* Paragraph text can now explicitly be spanned (#58)
|
||||||
Thanks to @c-b-h
|
<br>Thanks to @c-b-h
|
||||||
* Fix table border color if odd background is specified (#56)
|
* Fix table border color if odd background is specified (#56)
|
||||||
* Add table customizations (even and header rows)
|
* Add table customizations (even and header rows)
|
||||||
|
|
||||||
@ -98,10 +129,10 @@ to get the full picture of latest changes.
|
|||||||
* Update commonmark to 0.11.0 and android-gif to 1.2.14
|
* Update commonmark to 0.11.0 and android-gif to 1.2.14
|
||||||
* Add syntax highlight functionality (`library-syntax` module and `markwon-syntax` artifact)
|
* Add syntax highlight functionality (`library-syntax` module and `markwon-syntax` artifact)
|
||||||
* Add headingTypeface, headingTextSizes to SpannableTheme
|
* Add headingTypeface, headingTextSizes to SpannableTheme
|
||||||
Thanks to @edenman
|
<br>Thanks to @edenman
|
||||||
* Introduce `MediaDecoder` abstraction to `image-loader` module
|
* Introduce `MediaDecoder` abstraction to `image-loader` module
|
||||||
* Introduce `SpannableFactory`
|
* Introduce `SpannableFactory`
|
||||||
Thanks for idea to @c-b-h
|
<br>Thanks for idea to @c-b-h
|
||||||
* Update sample application to use syntax-highlight
|
* Update sample application to use syntax-highlight
|
||||||
* Update sample application to use clickable placeholder for GIF media
|
* Update sample application to use clickable placeholder for GIF media
|
||||||
|
|
||||||
@ -116,12 +147,12 @@ to `ru.noties.markwon.renderer` package (one level up, previously `ru.noties.mar
|
|||||||
* Change LinkSpan to extend URLSpan. Allow default linkColor (if not set explicitly)
|
* Change LinkSpan to extend URLSpan. Allow default linkColor (if not set explicitly)
|
||||||
* Fit an image without dimensions to canvas width (and keep ratio)
|
* Fit an image without dimensions to canvas width (and keep ratio)
|
||||||
* Add support for separate color for code blocks (#37)
|
* Add support for separate color for code blocks (#37)
|
||||||
Thanks to @Arcnor
|
<br>Thanks to @Arcnor
|
||||||
|
|
||||||
## v1.0.4
|
## v1.0.4
|
||||||
* Fixes #28 (tables are not rendered when at the end of the markdown)
|
* Fixes #28 (tables are not rendered when at the end of the markdown)
|
||||||
* Adds support for `indented code blocks`
|
* Adds support for `indented code blocks`
|
||||||
Thanks to @dlew
|
<br>Thanks to @dlew
|
||||||
|
|
||||||
## v1.0.3
|
## v1.0.3
|
||||||
* Fixed ordered lists (when number width is greater than block margin)
|
* Fixed ordered lists (when number width is greater than block margin)
|
||||||
|
@ -35,13 +35,14 @@ features listed in [commonmark-spec] are supported
|
|||||||
implementation "io.noties.markwon:core:${markwonVersion}"
|
implementation "io.noties.markwon:core:${markwonVersion}"
|
||||||
```
|
```
|
||||||
|
|
||||||
Full list of available artifacts is present in the [install section](https://noties.github.io/Markwon/docs/v3/install.html)
|
Full list of available artifacts is present in the [install section](https://noties.github.io/Markwon/docs/v4/install.html)
|
||||||
of the [documentation] web-site.
|
of the [documentation] web-site.
|
||||||
|
|
||||||
Please visit [documentation] web-site for further reference.
|
Please visit [documentation] web-site for further reference.
|
||||||
|
|
||||||
|
|
||||||
> You can find previous version of Markwon in [2.x.x](https://github.com/noties/Markwon/tree/2.x.x) branch
|
> You can find previous version of Markwon in [2.x.x](https://github.com/noties/Markwon/tree/2.x.x)
|
||||||
|
and [3.x.x](https://github.com/noties/Markwon/tree/3.x.x) branches
|
||||||
|
|
||||||
|
|
||||||
## Supported markdown features:
|
## Supported markdown features:
|
||||||
|
16
_CHANGES.md
16
_CHANGES.md
@ -1,16 +0,0 @@
|
|||||||
* `Markwon.builder` won't require CorePlugin registration (it is done automatically)
|
|
||||||
to create a builder without CorePlugin - use `Markwon#builderNoCore`
|
|
||||||
* `JLatex` plugin now is not dependent on ImagesPlugin
|
|
||||||
also accepts a ExecutorService (optional, by default cachedThreadPool is used)
|
|
||||||
* AsyncDrawableScheduler now can be called by multiple plugins without penalty
|
|
||||||
internally caches latest state and skips scheduling if drawables are already processed
|
|
||||||
* configure with registry
|
|
||||||
* removed priority
|
|
||||||
* images-plugin moved to standalone again
|
|
||||||
* removed MarkwonPlugin#configureHtmlRenderer -> now part of HtmlPlugin
|
|
||||||
* TagHandler now has `supportedTags()` method
|
|
||||||
* html is moved completely to html-plugin
|
|
||||||
* OnTextAddedListener (CorePlugin)
|
|
||||||
* ImageSizeResolver signature change (accept AsyncDrawable)
|
|
||||||
* JLatexMathPlugin builder has vertical & horizontal padding
|
|
||||||
* LinkResolver is now an independent entity (previously part of LinkSpan)
|
|
@ -34,7 +34,6 @@ dependencies {
|
|||||||
implementation project(':markwon-ext-tasklist')
|
implementation project(':markwon-ext-tasklist')
|
||||||
implementation project(':markwon-html')
|
implementation project(':markwon-html')
|
||||||
implementation project(':markwon-image')
|
implementation project(':markwon-image')
|
||||||
implementation project(':markwon-linkify')
|
|
||||||
implementation project(':markwon-syntax-highlight')
|
implementation project(':markwon-syntax-highlight')
|
||||||
|
|
||||||
deps.with {
|
deps.with {
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
# Image Glide
|
# Image Glide
|
||||||
|
|
||||||
<MavenBadge4 :artifact="'image-glide'" />
|
<MavenBadge4 :artifact="'image-glide'" />
|
||||||
|
|
||||||
|
Image loading based on `Glide` library
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
// automatically create Glide instance
|
||||||
|
.usePlugin(GlideImagesPlugin.create(context))
|
||||||
|
// use supplied Glide instance
|
||||||
|
.usePlugin(GlideImagesPlugin.create(Glide.with(context)))
|
||||||
|
// if you need more control
|
||||||
|
.usePlugin(GlideImagesPlugin.create(new GlideImagesPlugin.GlideStore() {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RequestBuilder<Drawable> load(@NonNull AsyncDrawable drawable) {
|
||||||
|
return Glide.with(context).load(drawable.getDestination());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel(@NonNull Target<?> target) {
|
||||||
|
Glide.with(context).clear(target);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
@ -1,3 +1,32 @@
|
|||||||
# Image Picasso
|
# Image Picasso
|
||||||
|
|
||||||
<MavenBadge4 :artifact="'image-picasso'" />
|
<MavenBadge4 :artifact="'image-picasso'" />
|
||||||
|
|
||||||
|
Image loading based on `Picasso` library
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
// automatically create Picasso instance
|
||||||
|
.usePlugin(PicassoImagesPlugin.create(context))
|
||||||
|
// use provided picasso instance
|
||||||
|
.usePlugin(PicassoImagesPlugin.create(Picasso.get()))
|
||||||
|
// if you need more control
|
||||||
|
.usePlugin(PicassoImagesPlugin.create(new PicassoImagesPlugin.PicassoStore() {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RequestCreator load(@NonNull AsyncDrawable drawable) {
|
||||||
|
return Picasso.get()
|
||||||
|
.load(drawable.getDestination())
|
||||||
|
// please note that drawable should be used as tag (not a destination)
|
||||||
|
// otherwise there won't be support for multiple images with the same URL
|
||||||
|
.tag(drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel(@NonNull AsyncDrawable drawable) {
|
||||||
|
Picasso.get()
|
||||||
|
.cancelTag(drawable);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
@ -194,15 +194,153 @@ introduce any unexpected behavior.
|
|||||||
|
|
||||||
### GifMediaDecoder
|
### GifMediaDecoder
|
||||||
|
|
||||||
|
Adds support for GIF media in markdown. If `pl.droidsonroids.gif:android-gif-drawable:*` dependency
|
||||||
|
is found in the classpath, then registration will happen automatically.
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
|
@Override
|
||||||
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
// autoplayGif controls if GIF should be automatically started
|
||||||
|
plugin.addMediaDecoder(GifMediaDecoder.create(/*autoplayGif*/false));
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
### SvgMediaDecoder
|
### SvgMediaDecoder
|
||||||
|
|
||||||
|
Adds support for SVG media in markdown. If `com.caverock:androidsvg:*` dependency is found
|
||||||
|
in the classpath, then registration will happen automatically.
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
|
@Override
|
||||||
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
|
||||||
|
// uses supplied Resources
|
||||||
|
plugin.addMediaDecoder(SvgMediaDecoder.create(context.getResources()));
|
||||||
|
|
||||||
|
// uses Resources.getSystem()
|
||||||
|
plugin.addMediaDecoder(SvgMediaDecoder.create());
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
### DefaultMediaDecoder
|
### DefaultMediaDecoder
|
||||||
|
|
||||||
|
`DefaultMediaDecoder` _tries_ to decode supplied InputStream
|
||||||
|
as Bitmap (via `BitmapFactory.decodeStream(inputStream)`). This decoder is registered automatically.
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
|
@Override
|
||||||
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
|
||||||
|
// uses supplied Resources
|
||||||
|
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(context.getResources()));
|
||||||
|
|
||||||
|
// uses Resources.getSystem()
|
||||||
|
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
## AsyncDrawableScheduler
|
## AsyncDrawableScheduler
|
||||||
|
|
||||||
|
`AsyncDrawableScheduler` is used in order to give `AsyncDrawable` a way to invalidate `TextView`
|
||||||
|
that is holding it. A plugin that is dealing with `AsyncDrawable` should always call these methods:
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(new AbstractMarkwonPlugin() {
|
||||||
|
@Override
|
||||||
|
public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) {
|
||||||
|
AsyncDrawableScheduler.unschedule(textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterSetText(@NonNull TextView textView) {
|
||||||
|
AsyncDrawableScheduler.schedule(textView);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Starting with <Badge text="4.0.0" /> multiple plugins can call `AsyncDrawableScheduler#schedule`
|
||||||
|
method without the penalty to process `AsyncDrawable` callbacks multiple times (internally caches
|
||||||
|
state which ensures that a `TextView` is processed only once the text has changed).
|
||||||
|
:::
|
||||||
|
|
||||||
## ErrorHandler
|
## ErrorHandler
|
||||||
|
|
||||||
## Placeholder
|
An `ErrorHandler` can be used to receive an error that has happened during image loading
|
||||||
|
and (optionally) return an error drawable to be displayed instead
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
|
@Override
|
||||||
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
plugin.errorHandler(new ImagesPlugin.ErrorHandler() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Drawable handleError(@NonNull String url, @NonNull Throwable throwable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
## PlaceholderProvider
|
||||||
|
|
||||||
|
To display a placeholder during image loading `PlaceholderProvider` can be used:
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
|
@Override
|
||||||
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If your placeholder drawable has _specific_ size which is not the same an image that is being loaded,
|
||||||
|
you can manually assign bounds to the placeholder:
|
||||||
|
|
||||||
|
```java
|
||||||
|
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
|
||||||
|
@Override
|
||||||
|
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
|
||||||
|
final ColorDrawable placeholder = new ColorDrawable(Color.BLUE);
|
||||||
|
// these bounds will be used to display a placeholder,
|
||||||
|
// so even if loading image has size `width=100%`, placeholder
|
||||||
|
// bounds won't be affected by it
|
||||||
|
placeholder.setBounds(0, 0, 48, 48);
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
If you are using [html](/docs/v4/html/) you do not have to additionally setup
|
If you are using [html](/docs/v4/html/) you do not have to additionally setup
|
||||||
|
@ -1,3 +1,31 @@
|
|||||||
# Linkify
|
# Linkify
|
||||||
|
|
||||||
<MavenBadge4 :artifact="'linkify'" />
|
<MavenBadge4 :artifact="'linkify'" />
|
||||||
|
|
||||||
|
A plugin to automatically add links to your markdown. Currently autolinking works for:
|
||||||
|
* email (`me@web.com`)
|
||||||
|
* phone numbers (`+10000000`)
|
||||||
|
* web URLS
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
`Linkify` plugin is based on `android.text.util.Linkify` which can lead to significant performance
|
||||||
|
drop due to its implementation based on regex.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::danger
|
||||||
|
Do not use `autolink` XML attribute on your `TextView` as it will remove
|
||||||
|
all links except autolinked ones ¯\\\_(ツ)_/¯
|
||||||
|
:::
|
||||||
|
|
||||||
|
```java
|
||||||
|
final Markwon markwon = Markwon.builder(context)
|
||||||
|
// will autolink all supported types
|
||||||
|
.usePlugin(LinkifyPlugin.create())
|
||||||
|
// the same as above
|
||||||
|
.usePlugin(LinkifyPlugin.create(
|
||||||
|
Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS | Linkify.WEB_URLS
|
||||||
|
))
|
||||||
|
// only emails
|
||||||
|
.usePlugin(LinkifyPlugin.create(Linkify.EMAIL_ADDRESSES))
|
||||||
|
.build();
|
||||||
|
```
|
@ -2,5 +2,6 @@
|
|||||||
|
|
||||||
* maven group-id is changed: `io.noties.markwon` (was `ru.noties.markwon`)
|
* maven group-id is changed: `io.noties.markwon` (was `ru.noties.markwon`)
|
||||||
* root package-name is changed: `io.noties.markwon` (was `ru.noties.markwon`)
|
* root package-name is changed: `io.noties.markwon` (was `ru.noties.markwon`)
|
||||||
|
* `androidx` packages
|
||||||
|
|
||||||
todo
|
todo
|
@ -60,3 +60,11 @@ This extension will be applied to a text like this:
|
|||||||
```md
|
```md
|
||||||
@@we are inside different delimiter characters$$
|
@@we are inside different delimiter characters$$
|
||||||
```
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Space character cannot be used as a delimiter (from either side). So,
|
||||||
|
```java
|
||||||
|
plugin.addExtension(1, '@', ' ', /*spanFactory*/);
|
||||||
|
```
|
||||||
|
won't work for `@some-text ` text
|
||||||
|
:::
|
||||||
|
@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
|
|||||||
/**
|
/**
|
||||||
* @see LinkResolverDef
|
* @see LinkResolverDef
|
||||||
* @see MarkwonConfiguration.Builder#linkResolver(LinkResolver)
|
* @see MarkwonConfiguration.Builder#linkResolver(LinkResolver)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface LinkResolver {
|
public interface LinkResolver {
|
||||||
void resolve(@NonNull View view, @NonNull String link);
|
void resolve(@NonNull View view, @NonNull String link);
|
||||||
|
@ -47,14 +47,14 @@ public abstract class Markwon {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static Builder builder(@NonNull Context context) {
|
public static Builder builder(@NonNull Context context) {
|
||||||
return new MarkwonBuilderImpl(context)
|
return new MarkwonBuilderImpl(context)
|
||||||
// @since 4.0.0-SNAPSHOT add CorePlugin
|
// @since 4.0.0 add CorePlugin
|
||||||
.usePlugin(CorePlugin.create());
|
.usePlugin(CorePlugin.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to obtain an instance of {@link Builder} without {@link CorePlugin}.
|
* Factory method to obtain an instance of {@link Builder} without {@link CorePlugin}.
|
||||||
*
|
*
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static Builder builderNoCore(@NonNull Context context) {
|
public static Builder builderNoCore(@NonNull Context context) {
|
||||||
|
@ -95,7 +95,7 @@ public class MarkwonConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder asyncDrawableLoader(@NonNull AsyncDrawableLoader asyncDrawableLoader) {
|
public Builder asyncDrawableLoader(@NonNull AsyncDrawableLoader asyncDrawableLoader) {
|
||||||
@ -138,7 +138,7 @@ public class MarkwonConfiguration {
|
|||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
this.spansFactory = spansFactory;
|
this.spansFactory = spansFactory;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
if (asyncDrawableLoader == null) {
|
if (asyncDrawableLoader == null) {
|
||||||
asyncDrawableLoader = AsyncDrawableLoader.noOp();
|
asyncDrawableLoader = AsyncDrawableLoader.noOp();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ public interface MarkwonPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Registry#require(Class, Action)
|
* @see Registry#require(Class, Action)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
interface Action<P extends MarkwonPlugin> {
|
interface Action<P extends MarkwonPlugin> {
|
||||||
void apply(@NonNull P p);
|
void apply(@NonNull P p);
|
||||||
@ -34,7 +34,7 @@ public interface MarkwonPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #configure(Registry)
|
* @see #configure(Registry)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
interface Registry {
|
interface Registry {
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public interface MarkwonPlugin {
|
|||||||
/**
|
/**
|
||||||
* This method will be called before any other during {@link Markwon} instance construction.
|
* This method will be called before any other during {@link Markwon} instance construction.
|
||||||
*
|
*
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
void configure(@NonNull Registry registry);
|
void configure(@NonNull Registry registry);
|
||||||
|
|
||||||
@ -91,14 +91,6 @@ public interface MarkwonPlugin {
|
|||||||
*/
|
*/
|
||||||
void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder);
|
void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder);
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Configure {@link MarkwonHtmlRenderer} to add or remove HTML {@link TagHandler}s
|
|
||||||
// *
|
|
||||||
// * @see MarkwonHtmlRenderer
|
|
||||||
// * @see MarkwonHtmlRenderer.Builder
|
|
||||||
// */
|
|
||||||
// void configureHtmlRenderer(@NonNull MarkwonHtmlRenderer.Builder builder);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process input markdown and return new string to be used in parsing stage further.
|
* Process input markdown and return new string to be used in parsing stage further.
|
||||||
* Can be described as <code>pre-processing</code> of markdown String.
|
* Can be described as <code>pre-processing</code> of markdown String.
|
||||||
|
@ -10,7 +10,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import io.noties.markwon.core.CorePlugin;
|
import io.noties.markwon.core.CorePlugin;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
class RegistryImpl implements MarkwonPlugin.Registry {
|
class RegistryImpl implements MarkwonPlugin.Registry {
|
||||||
|
|
||||||
private final List<MarkwonPlugin> origin;
|
private final List<MarkwonPlugin> origin;
|
||||||
|
@ -58,7 +58,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #addOnTextAddedListener(OnTextAddedListener)
|
* @see #addOnTextAddedListener(OnTextAddedListener)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface OnTextAddedListener {
|
public interface OnTextAddedListener {
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
|||||||
return new CorePlugin();
|
return new CorePlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private final List<OnTextAddedListener> onTextAddedListeners = new ArrayList<>(0);
|
private final List<OnTextAddedListener> onTextAddedListeners = new ArrayList<>(0);
|
||||||
|
|
||||||
protected CorePlugin() {
|
protected CorePlugin() {
|
||||||
@ -98,7 +98,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
|||||||
* Can be useful to post-process text added. For example for auto-linking capabilities.
|
* Can be useful to post-process text added. For example for auto-linking capabilities.
|
||||||
*
|
*
|
||||||
* @see OnTextAddedListener
|
* @see OnTextAddedListener
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -171,7 +171,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
visitor.builder().append(literal);
|
visitor.builder().append(literal);
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
if (!onTextAddedListeners.isEmpty()) {
|
if (!onTextAddedListeners.isEmpty()) {
|
||||||
// calculate the start position
|
// calculate the start position
|
||||||
final int length = visitor.length() - literal.length();
|
final int length = visitor.length() - literal.length();
|
||||||
@ -262,7 +262,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
// his method is moved from ImagesPlugin. Alternative implementations must set SpanFactory
|
// his method is moved from ImagesPlugin. Alternative implementations must set SpanFactory
|
||||||
// for Image node in order for this visitor to function
|
// for Image node in order for this visitor to function
|
||||||
private static void image(MarkwonVisitor.Builder builder) {
|
private static void image(MarkwonVisitor.Builder builder) {
|
||||||
|
@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Px;
|
import androidx.annotation.Px;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class LastLineSpacingSpan implements LineHeightSpan {
|
public class LastLineSpacingSpan implements LineHeightSpan {
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public ImageSize getImageSize() {
|
public ImageSize getImageSize() {
|
||||||
@ -61,7 +61,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImageSizeResolver getImageSizeResolver() {
|
public ImageSizeResolver getImageSizeResolver() {
|
||||||
@ -69,7 +69,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public boolean hasKnownDimentions() {
|
public boolean hasKnownDimentions() {
|
||||||
return canvasWidth > 0;
|
return canvasWidth > 0;
|
||||||
@ -77,7 +77,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #hasKnownDimentions()
|
* @see #hasKnownDimentions()
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public int getLastKnownCanvasWidth() {
|
public int getLastKnownCanvasWidth() {
|
||||||
return canvasWidth;
|
return canvasWidth;
|
||||||
@ -85,7 +85,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #hasKnownDimentions()
|
* @see #hasKnownDimentions()
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public float getLastKnowTextSize() {
|
public float getLastKnowTextSize() {
|
||||||
return textSize;
|
return textSize;
|
||||||
@ -262,7 +262,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
if (hasResult()) {
|
if (hasResult()) {
|
||||||
out = result.getIntrinsicWidth();
|
out = result.getIntrinsicWidth();
|
||||||
} else {
|
} else {
|
||||||
// @since 4.0.0-SNAPSHOT, must not be zero in order to receive canvas dimensions
|
// @since 4.0.0, must not be zero in order to receive canvas dimensions
|
||||||
out = 1;
|
out = 1;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@ -274,7 +274,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
if (hasResult()) {
|
if (hasResult()) {
|
||||||
out = result.getIntrinsicHeight();
|
out = result.getIntrinsicHeight();
|
||||||
} else {
|
} else {
|
||||||
// @since 4.0.0-SNAPSHOT, must not be zero in order to receive canvas dimensions
|
// @since 4.0.0, must not be zero in order to receive canvas dimensions
|
||||||
out = 1;
|
out = 1;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
@ -16,12 +16,12 @@ public abstract class AsyncDrawableLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.1.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract void load(@NonNull AsyncDrawable drawable);
|
public abstract void load(@NonNull AsyncDrawable drawable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.1.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract void cancel(@NonNull AsyncDrawable drawable);
|
public abstract void cancel(@NonNull AsyncDrawable drawable);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public abstract class AsyncDrawableScheduler {
|
|||||||
// hm... we need the same thing for unschedule then... we can check if last hash is !null,
|
// hm... we need the same thing for unschedule then... we can check if last hash is !null,
|
||||||
// if it's not -> unschedule, else ignore
|
// if it's not -> unschedule, else ignore
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
final Integer lastTextHashCode =
|
final Integer lastTextHashCode =
|
||||||
(Integer) textView.getTag(R.id.markwon_drawables_scheduler_last_text_hashcode);
|
(Integer) textView.getTag(R.id.markwon_drawables_scheduler_last_text_hashcode);
|
||||||
final int textHashCode = textView.getText().hashCode();
|
final int textHashCode = textView.getText().hashCode();
|
||||||
@ -69,7 +69,7 @@ public abstract class AsyncDrawableScheduler {
|
|||||||
// must be called when text manually changed in TextView
|
// must be called when text manually changed in TextView
|
||||||
public static void unschedule(@NonNull TextView view) {
|
public static void unschedule(@NonNull TextView view) {
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
if (view.getTag(R.id.markwon_drawables_scheduler_last_text_hashcode) == null) {
|
if (view.getTag(R.id.markwon_drawables_scheduler_last_text_hashcode) == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ public abstract class AsyncDrawableScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we also could've tried the `nextSpanTransition`, but strangely it leads to worse performance
|
// we also could've tried the `nextSpanTransition`, but strangely it leads to worse performance
|
||||||
// then direct getSpans
|
// than direct getSpans
|
||||||
|
|
||||||
return ((Spanned) cs).getSpans(0, length, AsyncDrawableSpan.class);
|
return ((Spanned) cs).getSpans(0, length, AsyncDrawableSpan.class);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import androidx.annotation.NonNull;
|
|||||||
public abstract class ImageSizeResolver {
|
public abstract class ImageSizeResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract Rect resolveImageSize(@NonNull AsyncDrawable drawable);
|
public abstract Rect resolveImageSize(@NonNull AsyncDrawable drawable);
|
||||||
|
@ -31,7 +31,7 @@ public class ImageSizeResolverDefTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void correct_redirect() {
|
public void correct_redirect() {
|
||||||
// @since 4.0.0-SNAPSHOT the main method is changed to accept AsyncDrawable
|
// @since 4.0.0 the main method is changed to accept AsyncDrawable
|
||||||
|
|
||||||
final ImageSizeResolverDef def = mock(ImageSizeResolverDef.class, Mockito.CALLS_REAL_METHODS);
|
final ImageSizeResolverDef def = mock(ImageSizeResolverDef.class, Mockito.CALLS_REAL_METHODS);
|
||||||
final AsyncDrawable drawable = mock(AsyncDrawable.class);
|
final AsyncDrawable drawable = mock(AsyncDrawable.class);
|
||||||
|
@ -36,7 +36,7 @@ import ru.noties.jlatexmath.JLatexMathDrawable;
|
|||||||
public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface BackgroundProvider {
|
public interface BackgroundProvider {
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -73,7 +73,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private final float textSize;
|
private final float textSize;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private final BackgroundProvider backgroundProvider;
|
private final BackgroundProvider backgroundProvider;
|
||||||
|
|
||||||
@JLatexMathDrawable.Align
|
@JLatexMathDrawable.Align
|
||||||
@ -81,13 +81,13 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private final boolean fitCanvas;
|
private final boolean fitCanvas;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private final int paddingHorizontal;
|
private final int paddingHorizontal;
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
|
|
||||||
private final int paddingVertical;
|
private final int paddingVertical;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
Config(@NonNull Builder builder) {
|
Config(@NonNull Builder builder) {
|
||||||
@ -98,7 +98,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
this.paddingHorizontal = builder.paddingHorizontal;
|
this.paddingHorizontal = builder.paddingHorizontal;
|
||||||
this.paddingVertical = builder.paddingVertical;
|
this.paddingVertical = builder.paddingVertical;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
ExecutorService executorService = builder.executorService;
|
ExecutorService executorService = builder.executorService;
|
||||||
if (executorService == null) {
|
if (executorService == null) {
|
||||||
executorService = Executors.newCachedThreadPool();
|
executorService = Executors.newCachedThreadPool();
|
||||||
@ -164,7 +164,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private final float textSize;
|
private final float textSize;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private BackgroundProvider backgroundProvider;
|
private BackgroundProvider backgroundProvider;
|
||||||
|
|
||||||
@JLatexMathDrawable.Align
|
@JLatexMathDrawable.Align
|
||||||
@ -172,13 +172,13 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private boolean fitCanvas = true;
|
private boolean fitCanvas = true;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private int paddingHorizontal;
|
private int paddingHorizontal;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private int paddingVertical;
|
private int paddingVertical;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private ExecutorService executorService;
|
private ExecutorService executorService;
|
||||||
|
|
||||||
Builder(float textSize) {
|
Builder(float textSize) {
|
||||||
@ -211,7 +211,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder builder(@Px int paddingHorizontal, @Px int paddingVertical) {
|
public Builder builder(@Px int paddingHorizontal, @Px int paddingVertical) {
|
||||||
@ -221,7 +221,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder executorService(@NonNull ExecutorService executorService) {
|
public Builder executorService(@NonNull ExecutorService executorService) {
|
||||||
@ -235,7 +235,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private static class JLatextAsyncDrawableLoader extends AsyncDrawableLoader {
|
private static class JLatextAsyncDrawableLoader extends AsyncDrawableLoader {
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
@ -317,7 +317,7 @@ public class JLatexMathPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we must make drawable fit canvas (if specified), but do not keep the ratio whilst scaling up
|
// we must make drawable fit canvas (if specified), but do not keep the ratio whilst scaling up
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
private static class JLatexImageSizeResolver extends ImageSizeResolver {
|
private static class JLatexImageSizeResolver extends ImageSizeResolver {
|
||||||
|
|
||||||
private final boolean fitCanvas;
|
private final boolean fitCanvas;
|
||||||
|
@ -29,7 +29,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #create(HtmlConfigure)
|
* @see #create(HtmlConfigure)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface HtmlConfigure {
|
public interface HtmlConfigure {
|
||||||
void configureHtml(@NonNull HtmlPlugin plugin);
|
void configureHtml(@NonNull HtmlPlugin plugin);
|
||||||
@ -41,7 +41,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static HtmlPlugin create(@NonNull HtmlConfigure configure) {
|
public static HtmlPlugin create(@NonNull HtmlConfigure configure) {
|
||||||
@ -65,7 +65,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
/**
|
/**
|
||||||
* @param allowNonClosedTags whether or not non-closed tags should be closed
|
* @param allowNonClosedTags whether or not non-closed tags should be closed
|
||||||
* at the document end. By default `false`
|
* at the document end. By default `false`
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public HtmlPlugin allowNonClosedTags(boolean allowNonClosedTags) {
|
public HtmlPlugin allowNonClosedTags(boolean allowNonClosedTags) {
|
||||||
@ -74,7 +74,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public HtmlPlugin addHandler(@NonNull TagHandler tagHandler) {
|
public HtmlPlugin addHandler(@NonNull TagHandler tagHandler) {
|
||||||
@ -83,7 +83,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public TagHandler getHandler(@NonNull String tagName) {
|
public TagHandler getHandler(@NonNull String tagName) {
|
||||||
@ -96,7 +96,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
* {@link TagHandlerNoOp} to no-op certain default tags.
|
* {@link TagHandlerNoOp} to no-op certain default tags.
|
||||||
*
|
*
|
||||||
* @see TagHandlerNoOp
|
* @see TagHandlerNoOp
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public HtmlPlugin excludeDefaults(boolean excludeDefaults) {
|
public HtmlPlugin excludeDefaults(boolean excludeDefaults) {
|
||||||
@ -107,7 +107,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder configurationBuilder) {
|
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder configurationBuilder) {
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT we init internal html-renderer here (marks the end of configuration)
|
// @since 4.0.0 we init internal html-renderer here (marks the end of configuration)
|
||||||
|
|
||||||
final MarkwonHtmlRendererImpl.Builder builder = this.builder;
|
final MarkwonHtmlRendererImpl.Builder builder = this.builder;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ public abstract class TagHandler {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract Collection<String> supportedTags();
|
public abstract Collection<String> supportedTags();
|
||||||
|
@ -9,7 +9,7 @@ import java.util.Collections;
|
|||||||
import io.noties.markwon.MarkwonVisitor;
|
import io.noties.markwon.MarkwonVisitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class TagHandlerNoOp extends TagHandler {
|
public class TagHandlerNoOp extends TagHandler {
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import io.noties.markwon.image.DrawableUtils;
|
|||||||
import io.noties.markwon.image.ImageSpanFactory;
|
import io.noties.markwon.image.ImageSpanFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class GlideImagesPlugin extends AbstractMarkwonPlugin {
|
public class GlideImagesPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import io.noties.markwon.image.DrawableUtils;
|
|||||||
import io.noties.markwon.image.ImageSpanFactory;
|
import io.noties.markwon.image.ImageSpanFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class PicassoImagesPlugin extends AbstractMarkwonPlugin {
|
public class PicassoImagesPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class AsyncDrawableLoaderBuilder {
|
|||||||
|
|
||||||
AsyncDrawableLoaderBuilder() {
|
AsyncDrawableLoaderBuilder() {
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
// okay, let's add supported schemes at the start, this would be : data-uri and default network
|
// okay, let's add supported schemes at the start, this would be : data-uri and default network
|
||||||
// we should not use file-scheme as it's a bit complicated to assume file usage (lack of permissions)
|
// we should not use file-scheme as it's a bit complicated to assume file usage (lack of permissions)
|
||||||
addSchemeHandler(DataUriSchemeHandler.create());
|
addSchemeHandler(DataUriSchemeHandler.create());
|
||||||
|
@ -28,7 +28,7 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
|
|||||||
|
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT use a hash-map with a AsyncDrawable as key for multiple requests
|
// @since 4.0.0 use a hash-map with a AsyncDrawable as key for multiple requests
|
||||||
// for the same destination
|
// for the same destination
|
||||||
private final Map<AsyncDrawable, Future<?>> requests = new HashMap<>(2);
|
private final Map<AsyncDrawable, Future<?>> requests = new HashMap<>(2);
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
|
|||||||
this(builder, new Handler(Looper.getMainLooper()));
|
this(builder, new Handler(Looper.getMainLooper()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
AsyncDrawableLoaderImpl(@NonNull AsyncDrawableLoaderBuilder builder, @NonNull Handler handler) {
|
AsyncDrawableLoaderImpl(@NonNull AsyncDrawableLoaderBuilder builder, @NonNull Handler handler) {
|
||||||
this.executorService = builder.executorService;
|
this.executorService = builder.executorService;
|
||||||
@ -144,7 +144,7 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
|
|||||||
|
|
||||||
final Drawable out = drawable;
|
final Drawable out = drawable;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT apply intrinsic bounds (but only if they are empty)
|
// @since 4.0.0 apply intrinsic bounds (but only if they are empty)
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
final Rect bounds = out.getBounds();
|
final Rect bounds = out.getBounds();
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@ -17,7 +17,7 @@ public abstract class ImageItem {
|
|||||||
*
|
*
|
||||||
* @see #withDecodingNeeded(String, InputStream)
|
* @see #withDecodingNeeded(String, InputStream)
|
||||||
* @see WithResult
|
* @see WithResult
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ImageItem withResult(@NonNull Drawable drawable) {
|
public static ImageItem withResult(@NonNull Drawable drawable) {
|
||||||
@ -29,7 +29,7 @@ public abstract class ImageItem {
|
|||||||
*
|
*
|
||||||
* @see #withResult(Drawable)
|
* @see #withResult(Drawable)
|
||||||
* @see WithDecodingNeeded
|
* @see WithDecodingNeeded
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ImageItem withDecodingNeeded(
|
public static ImageItem withDecodingNeeded(
|
||||||
@ -43,31 +43,31 @@ public abstract class ImageItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasResult();
|
public abstract boolean hasResult();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasDecodingNeeded();
|
public abstract boolean hasDecodingNeeded();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #hasResult()
|
* @see #hasResult()
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract WithResult getAsWithResult();
|
public abstract WithResult getAsWithResult();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #hasDecodingNeeded()
|
* @see #hasDecodingNeeded()
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract WithDecodingNeeded getAsWithDecodingNeeded();
|
public abstract WithDecodingNeeded getAsWithDecodingNeeded();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public static class WithResult extends ImageItem {
|
public static class WithResult extends ImageItem {
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ public abstract class ImageItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public static class WithDecodingNeeded extends ImageItem {
|
public static class WithDecodingNeeded extends ImageItem {
|
||||||
|
|
||||||
|
@ -27,14 +27,14 @@ import io.noties.markwon.image.svg.SvgMediaDecoder;
|
|||||||
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface ImagesConfigure {
|
public interface ImagesConfigure {
|
||||||
void configureImages(@NonNull ImagesPlugin plugin);
|
void configureImages(@NonNull ImagesPlugin plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface PlaceholderProvider {
|
public interface PlaceholderProvider {
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -42,7 +42,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public interface ErrorHandler {
|
public interface ErrorHandler {
|
||||||
|
|
||||||
@ -74,12 +74,12 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private final AsyncDrawableLoaderBuilder builder;
|
private final AsyncDrawableLoaderBuilder builder;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
ImagesPlugin() {
|
ImagesPlugin() {
|
||||||
this(new AsyncDrawableLoaderBuilder());
|
this(new AsyncDrawableLoaderBuilder());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ImagesPlugin(@NonNull AsyncDrawableLoaderBuilder builder) {
|
ImagesPlugin(@NonNull AsyncDrawableLoaderBuilder builder) {
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
@ -88,7 +88,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
/**
|
/**
|
||||||
* Optional (by default new cached thread executor will be used)
|
* Optional (by default new cached thread executor will be used)
|
||||||
*
|
*
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin executorService(@NonNull ExecutorService executorService) {
|
public ImagesPlugin executorService(@NonNull ExecutorService executorService) {
|
||||||
@ -102,7 +102,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
* @see FileSchemeHandler
|
* @see FileSchemeHandler
|
||||||
* @see NetworkSchemeHandler
|
* @see NetworkSchemeHandler
|
||||||
* @see OkHttpNetworkSchemeHandler
|
* @see OkHttpNetworkSchemeHandler
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin addSchemeHandler(@NonNull SchemeHandler schemeHandler) {
|
public ImagesPlugin addSchemeHandler(@NonNull SchemeHandler schemeHandler) {
|
||||||
@ -114,7 +114,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
* @see DefaultMediaDecoder
|
* @see DefaultMediaDecoder
|
||||||
* @see SvgMediaDecoder
|
* @see SvgMediaDecoder
|
||||||
* @see GifMediaDecoder
|
* @see GifMediaDecoder
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin addMediaDecoder(@NonNull MediaDecoder mediaDecoder) {
|
public ImagesPlugin addMediaDecoder(@NonNull MediaDecoder mediaDecoder) {
|
||||||
@ -127,7 +127,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
* if you need to disable default-image-media-decoder specify here own no-op implementation or null.
|
* if you need to disable default-image-media-decoder specify here own no-op implementation or null.
|
||||||
*
|
*
|
||||||
* @see DefaultMediaDecoder
|
* @see DefaultMediaDecoder
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) {
|
public ImagesPlugin defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) {
|
||||||
@ -136,7 +136,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin removeSchemeHandler(@NonNull String scheme) {
|
public ImagesPlugin removeSchemeHandler(@NonNull String scheme) {
|
||||||
@ -145,7 +145,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin removeMediaDecoder(@NonNull String contentType) {
|
public ImagesPlugin removeMediaDecoder(@NonNull String contentType) {
|
||||||
@ -154,7 +154,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin placeholderProvider(@NonNull PlaceholderProvider placeholderProvider) {
|
public ImagesPlugin placeholderProvider(@NonNull PlaceholderProvider placeholderProvider) {
|
||||||
@ -164,7 +164,7 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ErrorHandler
|
* @see ErrorHandler
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public ImagesPlugin errorHandler(@NonNull ErrorHandler errorHandler) {
|
public ImagesPlugin errorHandler(@NonNull ErrorHandler errorHandler) {
|
||||||
|
@ -27,7 +27,7 @@ public abstract class MediaDecoder {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract Collection<String> supportedTypes();
|
public abstract Collection<String> supportedTypes();
|
||||||
|
@ -24,7 +24,7 @@ public abstract class SchemeHandler {
|
|||||||
public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri);
|
public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract Collection<String> supportedSchemes();
|
public abstract Collection<String> supportedSchemes();
|
||||||
|
@ -40,7 +40,7 @@ public class FileSchemeHandler extends SchemeHandler {
|
|||||||
/**
|
/**
|
||||||
* @see #createWithAssets(AssetManager)
|
* @see #createWithAssets(AssetManager)
|
||||||
* @see UrlProcessorAndroidAssets
|
* @see UrlProcessorAndroidAssets
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static FileSchemeHandler createWithAssets(@NonNull Context context) {
|
public static FileSchemeHandler createWithAssets(@NonNull Context context) {
|
||||||
|
@ -26,7 +26,7 @@ public class GifMediaDecoder extends MediaDecoder {
|
|||||||
/**
|
/**
|
||||||
* Creates a {@link GifMediaDecoder} with {@code autoPlayGif = true}
|
* Creates a {@link GifMediaDecoder} with {@code autoPlayGif = true}
|
||||||
*
|
*
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static GifMediaDecoder create() {
|
public static GifMediaDecoder create() {
|
||||||
@ -43,7 +43,7 @@ public class GifMediaDecoder extends MediaDecoder {
|
|||||||
protected GifMediaDecoder(boolean autoPlayGif) {
|
protected GifMediaDecoder(boolean autoPlayGif) {
|
||||||
this.autoPlayGif = autoPlayGif;
|
this.autoPlayGif = autoPlayGif;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package io.noties.markwon.image.gif;
|
package io.noties.markwon.image.gif;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract class GifSupport {
|
public abstract class GifSupport {
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import okhttp3.Response;
|
|||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class OkHttpNetworkSchemeHandler extends SchemeHandler {
|
public class OkHttpNetworkSchemeHandler extends SchemeHandler {
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ public class OkHttpNetworkSchemeHandler extends SchemeHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static OkHttpNetworkSchemeHandler create(@NonNull Call.Factory factory) {
|
public static OkHttpNetworkSchemeHandler create(@NonNull Call.Factory factory) {
|
||||||
@ -44,7 +44,7 @@ public class OkHttpNetworkSchemeHandler extends SchemeHandler {
|
|||||||
|
|
||||||
private static final String HEADER_CONTENT_TYPE = "Content-Type";
|
private static final String HEADER_CONTENT_TYPE = "Content-Type";
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT, previously just OkHttpClient
|
// @since 4.0.0, previously just OkHttpClient
|
||||||
private final Call.Factory factory;
|
private final Call.Factory factory;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
@ -27,7 +27,7 @@ public class SvgMediaDecoder extends MediaDecoder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #create(Resources)
|
* @see #create(Resources)
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static SvgMediaDecoder create() {
|
public static SvgMediaDecoder create() {
|
||||||
@ -45,7 +45,7 @@ public class SvgMediaDecoder extends MediaDecoder {
|
|||||||
SvgMediaDecoder(Resources resources) {
|
SvgMediaDecoder(Resources resources) {
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package io.noties.markwon.image.svg;
|
package io.noties.markwon.image.svg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public abstract class SvgSupport {
|
public abstract class SvgSupport {
|
||||||
|
|
||||||
|
@ -1,9 +1,2 @@
|
|||||||
# Linkify
|
# Linkify
|
||||||
|
|
||||||
Use this module (or take a hint from it) if you would need _linkify_ capabilities. Do not
|
|
||||||
use `TextView.setAutolinkMask` (or specify `autolink` in XML) because it will remove all
|
|
||||||
existing links and keep only the ones it creates.
|
|
||||||
|
|
||||||
Please note that usage of this plugin introduces significant performance drop due to not
|
|
||||||
optimal implementation of underlying `android.text.util.Linkify`. If you have any ideas of how
|
|
||||||
to improve this - PRs are welcome!
|
|
@ -9,7 +9,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import io.noties.markwon.SpanFactory;
|
import io.noties.markwon.SpanFactory;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
class SimpleExtBuilder {
|
class SimpleExtBuilder {
|
||||||
|
|
||||||
private final List<DelimiterProcessor> extensions = new ArrayList<>(2);
|
private final List<DelimiterProcessor> extensions = new ArrayList<>(2);
|
||||||
|
@ -9,7 +9,7 @@ import org.commonmark.parser.delimiter.DelimiterRun;
|
|||||||
|
|
||||||
import io.noties.markwon.SpanFactory;
|
import io.noties.markwon.SpanFactory;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
class SimpleExtDelimiterProcessor implements DelimiterProcessor {
|
class SimpleExtDelimiterProcessor implements DelimiterProcessor {
|
||||||
|
|
||||||
private final char open;
|
private final char open;
|
||||||
|
@ -7,7 +7,7 @@ import org.commonmark.node.Visitor;
|
|||||||
|
|
||||||
import io.noties.markwon.SpanFactory;
|
import io.noties.markwon.SpanFactory;
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
// @since 4.0.0
|
||||||
class SimpleExtNode extends CustomNode {
|
class SimpleExtNode extends CustomNode {
|
||||||
|
|
||||||
private final SpanFactory spanFactory;
|
private final SpanFactory spanFactory;
|
||||||
|
@ -11,7 +11,7 @@ import io.noties.markwon.SpanFactory;
|
|||||||
import io.noties.markwon.SpannableBuilder;
|
import io.noties.markwon.SpannableBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0.0-SNAPSHOT
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class SimpleExtPlugin extends AbstractMarkwonPlugin {
|
public class SimpleExtPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<activity android:name="io.noties.markwon.sample.theme.ThemeActivity" />
|
<activity android:name="io.noties.markwon.sample.theme.ThemeActivity" />
|
||||||
<activity android:name=".html.HtmlActivity" />
|
<activity android:name=".html.HtmlActivity" />
|
||||||
<activity android:name=".simpleext.SimpleExtActivity" />
|
<activity android:name=".simpleext.SimpleExtActivity" />
|
||||||
|
<activity android:name=".customextension2.CustomExtensionActivity2" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import io.noties.markwon.Markwon;
|
|||||||
import io.noties.markwon.sample.basicplugins.BasicPluginsActivity;
|
import io.noties.markwon.sample.basicplugins.BasicPluginsActivity;
|
||||||
import io.noties.markwon.sample.core.CoreActivity;
|
import io.noties.markwon.sample.core.CoreActivity;
|
||||||
import io.noties.markwon.sample.customextension.CustomExtensionActivity;
|
import io.noties.markwon.sample.customextension.CustomExtensionActivity;
|
||||||
|
import io.noties.markwon.sample.customextension2.CustomExtensionActivity2;
|
||||||
import io.noties.markwon.sample.html.HtmlActivity;
|
import io.noties.markwon.sample.html.HtmlActivity;
|
||||||
import io.noties.markwon.sample.latex.LatexActivity;
|
import io.noties.markwon.sample.latex.LatexActivity;
|
||||||
import io.noties.markwon.sample.recycler.RecyclerActivity;
|
import io.noties.markwon.sample.recycler.RecyclerActivity;
|
||||||
@ -107,6 +108,10 @@ public class MainActivity extends Activity {
|
|||||||
activity = SimpleExtActivity.class;
|
activity = SimpleExtActivity.class;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CUSTOM_EXTENSION_2:
|
||||||
|
activity = CustomExtensionActivity2.class;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("No Activity is associated with sample-item: " + item);
|
throw new IllegalStateException("No Activity is associated with sample-item: " + item);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@ public enum Sample {
|
|||||||
|
|
||||||
HTML(R.string.sample_html),
|
HTML(R.string.sample_html),
|
||||||
|
|
||||||
SIMPLE_EXT(R.string.sample_simple_ext);
|
SIMPLE_EXT(R.string.sample_simple_ext),
|
||||||
|
|
||||||
|
CUSTOM_EXTENSION_2(R.string.sample_custom_extension_2);
|
||||||
|
|
||||||
private final int textResId;
|
private final int textResId;
|
||||||
|
|
||||||
|
@ -22,13 +22,6 @@ public class IconPlugin extends AbstractMarkwonPlugin {
|
|||||||
this.iconSpanProvider = iconSpanProvider;
|
this.iconSpanProvider = iconSpanProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @NonNull
|
|
||||||
// @Override
|
|
||||||
// public Priority priority() {
|
|
||||||
// // define images dependency
|
|
||||||
// return Priority.after(ImagesPlugin.class);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureParser(@NonNull Parser.Builder builder) {
|
public void configureParser(@NonNull Parser.Builder builder) {
|
||||||
builder.customDelimiterProcessor(IconProcessor.create());
|
builder.customDelimiterProcessor(IconProcessor.create());
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
package io.noties.markwon.sample.customextension2;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.commonmark.node.Link;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
|
import io.noties.markwon.Markwon;
|
||||||
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
|
import io.noties.markwon.MarkwonVisitor;
|
||||||
|
import io.noties.markwon.RenderProps;
|
||||||
|
import io.noties.markwon.SpannableBuilder;
|
||||||
|
import io.noties.markwon.core.CorePlugin;
|
||||||
|
import io.noties.markwon.core.CoreProps;
|
||||||
|
import io.noties.markwon.sample.R;
|
||||||
|
|
||||||
|
public class CustomExtensionActivity2 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);
|
||||||
|
|
||||||
|
// let's look for github special links:
|
||||||
|
// * `#1` - an issue or a pull request
|
||||||
|
// * `@user` link to a user
|
||||||
|
|
||||||
|
final Markwon markwon = Markwon.builder(this)
|
||||||
|
.usePlugin(new AbstractMarkwonPlugin() {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(CorePlugin.class, corePlugin ->
|
||||||
|
corePlugin.addOnTextAddedListener(new GithubLinkifyRegexTextAddedListener()));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final String md = "# Custom Extension 2\n" +
|
||||||
|
"\n" +
|
||||||
|
"This is an issue #1\n" +
|
||||||
|
"Done by @noties";
|
||||||
|
|
||||||
|
markwon.setMarkdown(textView, md);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class GithubLinkifyRegexTextAddedListener implements CorePlugin.OnTextAddedListener {
|
||||||
|
|
||||||
|
private static final Pattern PATTERN = Pattern.compile("((#\\d+)|(@\\w+))", Pattern.MULTILINE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextAdded(@NonNull MarkwonVisitor visitor, @NonNull String text, int start) {
|
||||||
|
|
||||||
|
final Matcher matcher = PATTERN.matcher(text);
|
||||||
|
|
||||||
|
String value;
|
||||||
|
String url;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
|
||||||
|
value = matcher.group(1);
|
||||||
|
|
||||||
|
// detect which one it is
|
||||||
|
if ('#' == value.charAt(0)) {
|
||||||
|
url = createIssueOrPullRequestLink(value.substring(1));
|
||||||
|
} else {
|
||||||
|
url = createUserLink(value.substring(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's important to use `start` value (represents start-index of `text` in the visitor)
|
||||||
|
index = start + matcher.start();
|
||||||
|
|
||||||
|
setLink(visitor, url, index, index + value.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private String createIssueOrPullRequestLink(@NonNull String number) {
|
||||||
|
// issues and pull-requests on github follow the same pattern and we
|
||||||
|
// cannot know for sure which one it is, but if we use issues for all types,
|
||||||
|
// github will automatically redirect to pull-request if it's the one which is opened
|
||||||
|
return "https://github.com/noties/Markwon/issues/" + number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private String createUserLink(@NonNull String user) {
|
||||||
|
return "https://github.com/" + user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLink(@NonNull MarkwonVisitor visitor, @NonNull String destination, int start, int end) {
|
||||||
|
|
||||||
|
// might a simpler one, but it doesn't respect possible changes to links
|
||||||
|
// visitor.builder().setSpan(
|
||||||
|
// new LinkSpan(visitor.configuration().theme(), destination, visitor.configuration().linkResolver()),
|
||||||
|
// start,
|
||||||
|
// end
|
||||||
|
// );
|
||||||
|
|
||||||
|
// use default handlers for links
|
||||||
|
final MarkwonConfiguration configuration = visitor.configuration();
|
||||||
|
final RenderProps renderProps = visitor.renderProps();
|
||||||
|
|
||||||
|
CoreProps.LINK_DESTINATION.set(renderProps, destination);
|
||||||
|
|
||||||
|
SpannableBuilder.setSpans(
|
||||||
|
visitor.builder(),
|
||||||
|
configuration.spansFactory().require(Link.class).getSpans(configuration, renderProps),
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,4 +20,7 @@
|
|||||||
<string name="sample_simple_ext"># \# SimpleExt\n\nShows how to use SimpleExtPlugin module
|
<string name="sample_simple_ext"># \# SimpleExt\n\nShows how to use SimpleExtPlugin module
|
||||||
to create own delimited parser extensions</string>
|
to create own delimited parser extensions</string>
|
||||||
|
|
||||||
|
<string name="sample_custom_extension_2"># \# Custom extension 2\n\nAutomatically
|
||||||
|
convert `#1` and `@user` to Github links</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user