ImageDestinationProcessor (before UrlProcessor), limit usage to images only
This commit is contained in:
parent
21152f368f
commit
171b6d40a0
@ -9,6 +9,7 @@
|
||||
* Expose `enabledBlockTypes` in `CorePlugin`
|
||||
* Update `jlatexmath-android` dependency ([#225])
|
||||
* Update `image-coil` module (Coil version `0.10.1`) ([#244])<br>Thanks to [@tylerbwong]
|
||||
* Rename `UrlProcessor` to `ImageDestinationProcessor` (`io.noties.markwon.urlprocessor` -> `io.noties.markwon.image.destination`) and limit its usage to process **only** destination URL of images (was used to also process links before)
|
||||
|
||||
[#235]: https://github.com/noties/Markwon/issues/235
|
||||
[#225]: https://github.com/noties/Markwon/issues/225
|
||||
|
@ -5,15 +5,15 @@ import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import io.noties.markwon.urlprocessor.UrlProcessor;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessor;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute;
|
||||
|
||||
class UrlProcessorInitialReadme implements UrlProcessor {
|
||||
class ImageDestinationProcessorInitialReadme extends ImageDestinationProcessor {
|
||||
|
||||
private static final String GITHUB_BASE = "https://github.com/noties/Markwon/raw/master/";
|
||||
|
||||
private final UrlProcessorRelativeToAbsolute processor
|
||||
= new UrlProcessorRelativeToAbsolute(GITHUB_BASE);
|
||||
private final ImageDestinationProcessorRelativeToAbsolute processor
|
||||
= new ImageDestinationProcessorRelativeToAbsolute(GITHUB_BASE);
|
||||
|
||||
@NonNull
|
||||
@Override
|
@ -24,6 +24,8 @@ import io.noties.markwon.ext.tables.TablePlugin;
|
||||
import io.noties.markwon.ext.tasklist.TaskListPlugin;
|
||||
import io.noties.markwon.html.HtmlPlugin;
|
||||
import io.noties.markwon.image.ImagesPlugin;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessor;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute;
|
||||
import io.noties.markwon.image.file.FileSchemeHandler;
|
||||
import io.noties.markwon.image.gif.GifMediaDecoder;
|
||||
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
||||
@ -31,8 +33,6 @@ import io.noties.markwon.syntax.Prism4jTheme;
|
||||
import io.noties.markwon.syntax.Prism4jThemeDarkula;
|
||||
import io.noties.markwon.syntax.Prism4jThemeDefault;
|
||||
import io.noties.markwon.syntax.SyntaxHighlightPlugin;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessor;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute;
|
||||
import io.noties.prism4j.Prism4j;
|
||||
|
||||
@ActivityScope
|
||||
@ -86,11 +86,11 @@ public class MarkdownRenderer {
|
||||
}
|
||||
|
||||
private void execute() {
|
||||
final UrlProcessor urlProcessor;
|
||||
final ImageDestinationProcessor imageDestinationProcessor;
|
||||
if (uri == null) {
|
||||
urlProcessor = new UrlProcessorInitialReadme();
|
||||
imageDestinationProcessor = new ImageDestinationProcessorInitialReadme();
|
||||
} else {
|
||||
urlProcessor = new UrlProcessorRelativeToAbsolute(uri.toString());
|
||||
imageDestinationProcessor = new ImageDestinationProcessorRelativeToAbsolute(uri.toString());
|
||||
}
|
||||
|
||||
final Prism4jTheme prism4jTheme = isLightTheme
|
||||
@ -119,7 +119,7 @@ public class MarkdownRenderer {
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
|
||||
builder.urlProcessor(urlProcessor);
|
||||
builder.imageDestinationProcessor(imageDestinationProcessor);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
@ -5,7 +5,7 @@ These are _configurable_ properties:
|
||||
* `AsyncDrawableLoader` (back here since <Badge text="4.0.0" />)
|
||||
* `SyntaxHighlight`
|
||||
* `LinkResolver` (since <Badge text="4.0.0" />, before — `LinkSpan.Resolver`)
|
||||
* `UrlProcessor`
|
||||
* `ImageDestinationProcessor` (since <Badge text="4.4.0" />, before — `UrlProcessor`)
|
||||
* `ImageSizeResolver`
|
||||
|
||||
:::tip
|
||||
@ -36,10 +36,11 @@ final Markwon markwon = Markwon.builder(context)
|
||||
.build();
|
||||
```
|
||||
|
||||
Currently `Markwon` provides 3 implementations for loading images:
|
||||
Currently `Markwon` provides 4 implementations for loading images:
|
||||
* [markwon implementation](/docs/v4/image/) with SVG, GIF, data uri and android_assets support
|
||||
* [based on Picasso](/docs/v4/image-picasso/)
|
||||
* [based on Glide](/docs/v4/image-glide/)
|
||||
* [base on Coil](/docs/v4/image-coil/)
|
||||
|
||||
## SyntaxHighlight
|
||||
|
||||
@ -87,32 +88,32 @@ if there is none registered. if you wish to register own instance of a `Movement
|
||||
apply it directly to a TextView or use [MovementMethodPlugin](/docs/v4/core/movement-method-plugin.md)
|
||||
:::
|
||||
|
||||
## UrlProcessor
|
||||
## ImageDestinationProcessor
|
||||
|
||||
Process URLs in your markdown (for links and images). If not provided explicitly,
|
||||
Process destinations (URLs) of images in your markdown. If not provided explicitly,
|
||||
default **no-op** implementation will be used, which does not modify URLs (keeping them as-is).
|
||||
|
||||
`Markwon` provides 2 implementations of `UrlProcessor`:
|
||||
* `UrlProcessorRelativeToAbsolute`
|
||||
* `UrlProcessorAndroidAssets`
|
||||
* `ImageDestinationProcessorRelativeToAbsolute`
|
||||
* `ImageDestinationProcessorAssets`
|
||||
|
||||
### UrlProcessorRelativeToAbsolute
|
||||
### ImageDestinationProcessorRelativeToAbsolute
|
||||
|
||||
`UrlProcessorRelativeToAbsolute` can be used to make relative URL absolute. For example if an image is
|
||||
defined like this: `` and `UrlProcessorRelativeToAbsolute`
|
||||
`ImageDestinationProcessorRelativeToAbsolute` can be used to make relative URL absolute. For example if an image is
|
||||
defined like this: `` and `ImageDestinationProcessorRelativeToAbsolute`
|
||||
is created with `https://github.com/noties/Markwon/raw/master/` as the base:
|
||||
`new UrlProcessorRelativeToAbsolute("https://github.com/noties/Markwon/raw/master/")`,
|
||||
`new ImageDestinationProcessorRelativeToAbsolute("https://github.com/noties/Markwon/raw/master/")`,
|
||||
then final image will have `https://github.com/noties/Markwon/raw/master/art/image.JPG`
|
||||
as the destination.
|
||||
|
||||
### UrlProcessorAndroidAssets
|
||||
### ImageDestinationProcessorAssets
|
||||
|
||||
`UrlProcessorAndroidAssets` can be used to make processed links to point to Android assets folder.
|
||||
`ImageDestinationProcessorAssets` can be used to make processed destinations to point to Android assets folder.
|
||||
So an image: `` will have `file:///android_asset/art/image.JPG` as the
|
||||
destination.
|
||||
|
||||
:::tip
|
||||
Please note that `UrlProcessorAndroidAssets` will process only URLs that have no `scheme` information,
|
||||
Please note that `ImageDestinationProcessorAssets` will process only URLs that have no `scheme` information,
|
||||
so a `./art/image.png` will become `file:///android_asset/art/image.JPG` whilst `https://so.me/where.png`
|
||||
will be kept as-is.
|
||||
:::
|
||||
|
@ -6,15 +6,13 @@ import io.noties.markwon.core.MarkwonTheme;
|
||||
import io.noties.markwon.image.AsyncDrawableLoader;
|
||||
import io.noties.markwon.image.ImageSizeResolver;
|
||||
import io.noties.markwon.image.ImageSizeResolverDef;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessor;
|
||||
import io.noties.markwon.syntax.SyntaxHighlight;
|
||||
import io.noties.markwon.syntax.SyntaxHighlightNoOp;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessor;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessorNoOp;
|
||||
|
||||
/**
|
||||
* since 3.0.0 renamed `SpannableConfiguration` -> `MarkwonConfiguration`
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class MarkwonConfiguration {
|
||||
|
||||
@NonNull
|
||||
@ -26,7 +24,8 @@ public class MarkwonConfiguration {
|
||||
private final AsyncDrawableLoader asyncDrawableLoader;
|
||||
private final SyntaxHighlight syntaxHighlight;
|
||||
private final LinkResolver linkResolver;
|
||||
private final UrlProcessor urlProcessor;
|
||||
// @since $nap;
|
||||
private final ImageDestinationProcessor imageDestinationProcessor;
|
||||
private final ImageSizeResolver imageSizeResolver;
|
||||
|
||||
// @since 3.0.0
|
||||
@ -37,7 +36,7 @@ public class MarkwonConfiguration {
|
||||
this.asyncDrawableLoader = builder.asyncDrawableLoader;
|
||||
this.syntaxHighlight = builder.syntaxHighlight;
|
||||
this.linkResolver = builder.linkResolver;
|
||||
this.urlProcessor = builder.urlProcessor;
|
||||
this.imageDestinationProcessor = builder.imageDestinationProcessor;
|
||||
this.imageSizeResolver = builder.imageSizeResolver;
|
||||
this.spansFactory = builder.spansFactory;
|
||||
}
|
||||
@ -62,9 +61,12 @@ public class MarkwonConfiguration {
|
||||
return linkResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since $nap;
|
||||
*/
|
||||
@NonNull
|
||||
public UrlProcessor urlProcessor() {
|
||||
return urlProcessor;
|
||||
public ImageDestinationProcessor imageDestinationProcessor() {
|
||||
return imageDestinationProcessor;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -87,7 +89,8 @@ public class MarkwonConfiguration {
|
||||
private AsyncDrawableLoader asyncDrawableLoader;
|
||||
private SyntaxHighlight syntaxHighlight;
|
||||
private LinkResolver linkResolver;
|
||||
private UrlProcessor urlProcessor;
|
||||
// @since $nap;
|
||||
private ImageDestinationProcessor imageDestinationProcessor;
|
||||
private ImageSizeResolver imageSizeResolver;
|
||||
private MarkwonSpansFactory spansFactory;
|
||||
|
||||
@ -115,9 +118,12 @@ public class MarkwonConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since $nap;
|
||||
*/
|
||||
@NonNull
|
||||
public Builder urlProcessor(@NonNull UrlProcessor urlProcessor) {
|
||||
this.urlProcessor = urlProcessor;
|
||||
public Builder imageDestinationProcessor(@NonNull ImageDestinationProcessor imageDestinationProcessor) {
|
||||
this.imageDestinationProcessor = imageDestinationProcessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -151,8 +157,9 @@ public class MarkwonConfiguration {
|
||||
linkResolver = new LinkResolverDef();
|
||||
}
|
||||
|
||||
if (urlProcessor == null) {
|
||||
urlProcessor = new UrlProcessorNoOp();
|
||||
// @since $nap;
|
||||
if (imageDestinationProcessor == null) {
|
||||
imageDestinationProcessor = ImageDestinationProcessor.noOp();
|
||||
}
|
||||
|
||||
if (imageSizeResolver == null) {
|
||||
|
@ -320,7 +320,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
final boolean link = parent instanceof Link;
|
||||
|
||||
final String destination = configuration
|
||||
.urlProcessor()
|
||||
.imageDestinationProcessor()
|
||||
.process(image.getDestination());
|
||||
|
||||
final RenderProps props = visitor.renderProps();
|
||||
@ -524,8 +524,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
final int length = visitor.length();
|
||||
visitor.visitChildren(link);
|
||||
|
||||
final MarkwonConfiguration configuration = visitor.configuration();
|
||||
final String destination = configuration.urlProcessor().process(link.getDestination());
|
||||
final String destination = link.getDestination();
|
||||
|
||||
CoreProps.LINK_DESTINATION.set(visitor.renderProps(), destination);
|
||||
|
||||
|
@ -0,0 +1,27 @@
|
||||
package io.noties.markwon.image.destination;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Process destination of image nodes
|
||||
*
|
||||
* @since $nap;
|
||||
*/
|
||||
public abstract class ImageDestinationProcessor {
|
||||
@NonNull
|
||||
public abstract String process(@NonNull String destination);
|
||||
|
||||
@NonNull
|
||||
public static ImageDestinationProcessor noOp() {
|
||||
return new NoOp();
|
||||
}
|
||||
|
||||
private static class NoOp extends ImageDestinationProcessor {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String process(@NonNull String destination) {
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package io.noties.markwon.image.destination;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ImageDestinationProcessor} that treats all destinations <strong>without scheme</strong>
|
||||
* information as pointing to the {@code assets} folder of an application. Please note that this
|
||||
* processor only adds required {@code file:///android_asset/} prefix to destinations and
|
||||
* actual image loading must take that into account (implement this functionality).
|
||||
* <p>
|
||||
* {@code FileSchemeHandler} from the {@code image} module supports asset images when created with
|
||||
* {@code createWithAssets} factory method
|
||||
*
|
||||
* @since $nap;
|
||||
*/
|
||||
public class ImageDestinationProcessorAssets extends ImageDestinationProcessor {
|
||||
|
||||
@NonNull
|
||||
public static ImageDestinationProcessorAssets create(@Nullable ImageDestinationProcessor parent) {
|
||||
return new ImageDestinationProcessorAssets(parent);
|
||||
}
|
||||
|
||||
static final String MOCK = "https://android.asset/";
|
||||
static final String BASE = "file:///android_asset/";
|
||||
|
||||
private final ImageDestinationProcessorRelativeToAbsolute assetsProcessor
|
||||
= new ImageDestinationProcessorRelativeToAbsolute(MOCK);
|
||||
|
||||
private final ImageDestinationProcessor processor;
|
||||
|
||||
public ImageDestinationProcessorAssets() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public ImageDestinationProcessorAssets(@Nullable ImageDestinationProcessor parent) {
|
||||
this.processor = parent;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String process(@NonNull String destination) {
|
||||
final String out;
|
||||
final Uri uri = Uri.parse(destination);
|
||||
if (TextUtils.isEmpty(uri.getScheme())) {
|
||||
out = assetsProcessor.process(destination).replace(MOCK, BASE);
|
||||
} else {
|
||||
if (processor != null) {
|
||||
out = processor.process(destination);
|
||||
} else {
|
||||
out = destination;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
package io.noties.markwon.image.destination;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -6,15 +6,30 @@ import androidx.annotation.Nullable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class UrlProcessorRelativeToAbsolute implements UrlProcessor {
|
||||
/**
|
||||
* @since $nap;
|
||||
*/
|
||||
public class ImageDestinationProcessorRelativeToAbsolute extends ImageDestinationProcessor {
|
||||
|
||||
@NonNull
|
||||
public static ImageDestinationProcessorRelativeToAbsolute create(@NonNull String base) {
|
||||
return new ImageDestinationProcessorRelativeToAbsolute(base);
|
||||
}
|
||||
|
||||
public static ImageDestinationProcessorRelativeToAbsolute create(@NonNull URL base) {
|
||||
return new ImageDestinationProcessorRelativeToAbsolute(base);
|
||||
}
|
||||
|
||||
private final URL base;
|
||||
|
||||
public UrlProcessorRelativeToAbsolute(@NonNull String base) {
|
||||
public ImageDestinationProcessorRelativeToAbsolute(@NonNull String base) {
|
||||
this.base = obtain(base);
|
||||
}
|
||||
|
||||
public ImageDestinationProcessorRelativeToAbsolute(@NonNull URL base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String process(@NonNull String destination) {
|
@ -1,8 +0,0 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public interface UrlProcessor {
|
||||
@NonNull
|
||||
String process(@NonNull String destination);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Processor that will <em>assume</em> that an URL without scheme points to android assets folder.
|
||||
* URL with a scheme will be processed by {@link #processor} (if it is specified) or returned `as-is`.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class UrlProcessorAndroidAssets implements UrlProcessor {
|
||||
|
||||
|
||||
static final String MOCK = "https://android.asset/";
|
||||
static final String BASE = "file:///android_asset/";
|
||||
|
||||
private final UrlProcessorRelativeToAbsolute assetsProcessor
|
||||
= new UrlProcessorRelativeToAbsolute(MOCK);
|
||||
|
||||
private final UrlProcessor processor;
|
||||
|
||||
public UrlProcessorAndroidAssets() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public UrlProcessorAndroidAssets(@Nullable UrlProcessor parent) {
|
||||
this.processor = parent;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String process(@NonNull String destination) {
|
||||
final String out;
|
||||
final Uri uri = Uri.parse(destination);
|
||||
if (TextUtils.isEmpty(uri.getScheme())) {
|
||||
out = assetsProcessor.process(destination).replace(MOCK, BASE);
|
||||
} else {
|
||||
if (processor != null) {
|
||||
out = processor.process(destination);
|
||||
} else {
|
||||
out = destination;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class UrlProcessorNoOp implements UrlProcessor {
|
||||
@NonNull
|
||||
@Override
|
||||
public String process(@NonNull String destination) {
|
||||
return destination;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
package io.noties.markwon.image.destination;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -6,18 +6,18 @@ import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static io.noties.markwon.image.destination.ImageDestinationProcessorAssets.BASE;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static io.noties.markwon.urlprocessor.UrlProcessorAndroidAssets.BASE;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class UrlProcessorAndroidAssetsTest {
|
||||
public class ImageDestinationProcessorAssetsTest {
|
||||
|
||||
private UrlProcessorAndroidAssets processor;
|
||||
private ImageDestinationProcessorAssets processor;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
processor = new UrlProcessorAndroidAssets();
|
||||
processor = new ImageDestinationProcessorAssets();
|
||||
}
|
||||
|
||||
@Test
|
@ -1,4 +1,4 @@
|
||||
package io.noties.markwon.urlprocessor;
|
||||
package io.noties.markwon.image.destination;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -9,39 +9,39 @@ import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class UrlProcessorRelativeToAbsoluteTest {
|
||||
public class ImageDestinationProcessorRelativeToAbsoluteTest {
|
||||
|
||||
@Test
|
||||
public void malformed_base_do_not_process() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("!@#$%^&*(");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("!@#$%^&*(");
|
||||
final String destination = "../hey.there.html";
|
||||
assertEquals(destination, processor.process(destination));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void access_root() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("https://ro.ot/hello/");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("https://ro.ot/hello/");
|
||||
final String url = "/index.html";
|
||||
assertEquals("https://ro.ot/index.html", processor.process(url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void access_same_directory() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("https://ro.ot/hello/");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("https://ro.ot/hello/");
|
||||
final String url = "./.htaccess";
|
||||
assertEquals("https://ro.ot/hello/.htaccess", processor.process(url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asset_directory_up() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("http://ro.ot/first/second/");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("http://ro.ot/first/second/");
|
||||
final String url = "../cat.JPG";
|
||||
assertEquals("http://ro.ot/first/cat.JPG", processor.process(url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void change_directory_inside_destination() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("http://ro.ot/first/");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("http://ro.ot/first/");
|
||||
final String url = "../first/../second/./thi.rd";
|
||||
assertEquals(
|
||||
"http://ro.ot/second/thi.rd",
|
||||
@ -51,7 +51,7 @@ public class UrlProcessorRelativeToAbsoluteTest {
|
||||
|
||||
@Test
|
||||
public void with_query_arguments() {
|
||||
final UrlProcessorRelativeToAbsolute processor = new UrlProcessorRelativeToAbsolute("http://ro.ot/first/");
|
||||
final ImageDestinationProcessorRelativeToAbsolute processor = new ImageDestinationProcessorRelativeToAbsolute("http://ro.ot/first/");
|
||||
final String url = "../index.php?ROOT=1";
|
||||
assertEquals(
|
||||
"http://ro.ot/index.php?ROOT=1",
|
@ -62,7 +62,7 @@ public class ImageHandler extends SimpleTagHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String destination = configuration.urlProcessor().process(src);
|
||||
final String destination = configuration.imageDestinationProcessor().process(src);
|
||||
final ImageSize imageSize = imageSizeParser.parse(tag.attributes());
|
||||
|
||||
// todo: replacement text is link... as we are not at block level
|
||||
|
@ -27,7 +27,8 @@ public class LinkHandler extends SimpleTagHandler {
|
||||
|
||||
CoreProps.LINK_DESTINATION.set(
|
||||
renderProps,
|
||||
configuration.urlProcessor().process(destination));
|
||||
destination
|
||||
);
|
||||
|
||||
return spanFactory.getSpans(configuration, renderProps);
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ package io.noties.markwon.image.file;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -18,7 +19,6 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.noties.markwon.urlprocessor.UrlProcessorAndroidAssets;
|
||||
import io.noties.markwon.image.ImageItem;
|
||||
import io.noties.markwon.image.SchemeHandler;
|
||||
|
||||
@ -30,7 +30,7 @@ public class FileSchemeHandler extends SchemeHandler {
|
||||
public static final String SCHEME = "file";
|
||||
|
||||
/**
|
||||
* @see UrlProcessorAndroidAssets
|
||||
* @see io.noties.markwon.image.destination.ImageDestinationProcessorAssets
|
||||
*/
|
||||
@NonNull
|
||||
public static FileSchemeHandler createWithAssets(@NonNull AssetManager assetManager) {
|
||||
@ -39,7 +39,7 @@ public class FileSchemeHandler extends SchemeHandler {
|
||||
|
||||
/**
|
||||
* @see #createWithAssets(AssetManager)
|
||||
* @see UrlProcessorAndroidAssets
|
||||
* @see io.noties.markwon.image.destination.ImageDestinationProcessorAssets
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@NonNull
|
||||
|
@ -5,6 +5,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.View;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -20,6 +21,7 @@ import java.util.Collections;
|
||||
|
||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||
import io.noties.markwon.BlockHandlerDef;
|
||||
import io.noties.markwon.LinkResolverDef;
|
||||
import io.noties.markwon.Markwon;
|
||||
import io.noties.markwon.MarkwonConfiguration;
|
||||
import io.noties.markwon.MarkwonSpansFactory;
|
||||
@ -153,7 +155,7 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions {
|
||||
* <ul>
|
||||
* <li>SyntaxHighlight</li>
|
||||
* <li>LinkSpan.Resolver</li>
|
||||
* <li>UrlProcessor</li>
|
||||
* <li>ImageDestinationProcessor</li>
|
||||
* <li>ImageSizeResolver</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
@ -173,12 +175,18 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions {
|
||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
|
||||
// for example if specified destination has no scheme info, we will
|
||||
// _assume_ that it's network request and append HTTPS scheme
|
||||
builder.urlProcessor(destination -> {
|
||||
final Uri uri = Uri.parse(destination);
|
||||
builder.linkResolver(new LinkResolverDef() {
|
||||
@Override
|
||||
public void resolve(@NonNull View view, @NonNull String link) {
|
||||
final String destination;
|
||||
final Uri uri = Uri.parse(link);
|
||||
if (TextUtils.isEmpty(uri.getScheme())) {
|
||||
return "https://" + destination;
|
||||
destination = "https://" + link;
|
||||
} else {
|
||||
destination = link;
|
||||
}
|
||||
super.resolve(view, destination);
|
||||
}
|
||||
return destination;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -34,6 +34,8 @@ import io.noties.markwon.MarkwonVisitor;
|
||||
import io.noties.markwon.core.CorePlugin;
|
||||
import io.noties.markwon.html.HtmlPlugin;
|
||||
import io.noties.markwon.image.ImagesPlugin;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessor;
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute;
|
||||
import io.noties.markwon.image.file.FileSchemeHandler;
|
||||
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
||||
import io.noties.markwon.image.svg.SvgMediaDecoder;
|
||||
@ -42,8 +44,6 @@ import io.noties.markwon.recycler.SimpleEntry;
|
||||
import io.noties.markwon.recycler.table.TableEntry;
|
||||
import io.noties.markwon.recycler.table.TableEntryPlugin;
|
||||
import io.noties.markwon.sample.R;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessor;
|
||||
import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute;
|
||||
|
||||
public class RecyclerActivity extends Activity {
|
||||
|
||||
@ -100,7 +100,7 @@ public class RecyclerActivity extends Activity {
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
|
||||
builder.urlProcessor(new UrlProcessorInitialReadme());
|
||||
builder.imageDestinationProcessor(new ImageDestinationProcessorInitialReadme());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -182,12 +182,12 @@ public class RecyclerActivity extends Activity {
|
||||
return out;
|
||||
}
|
||||
|
||||
private static class UrlProcessorInitialReadme implements UrlProcessor {
|
||||
private static class ImageDestinationProcessorInitialReadme extends ImageDestinationProcessor {
|
||||
|
||||
private static final String GITHUB_BASE = "https://github.com/noties/Markwon/raw/master/";
|
||||
|
||||
private final UrlProcessorRelativeToAbsolute processor
|
||||
= new UrlProcessorRelativeToAbsolute(GITHUB_BASE);
|
||||
private final ImageDestinationProcessorRelativeToAbsolute processor
|
||||
= new ImageDestinationProcessorRelativeToAbsolute(GITHUB_BASE);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user