Implicit LinkMovementMethod if not supplied explicitly

This commit is contained in:
Dimitry Ivanov 2019-01-13 16:57:16 +03:00
parent ba5bb9bfc7
commit 02e7539881
9 changed files with 112 additions and 131 deletions

View File

@ -7,7 +7,6 @@ import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@ -59,8 +58,6 @@ public class MainActivity extends Activity {
appBarRenderer.render(appBarState()); appBarRenderer.render(appBarState());
textView.setMovementMethod(LinkMovementMethod.getInstance());
markdownLoader.load(uri(), new MarkdownLoader.OnMarkdownTextLoaded() { markdownLoader.load(uri(), new MarkdownLoader.OnMarkdownTextLoaded() {
@Override @Override
public void apply(final String text) { public void apply(final String text) {

View File

@ -1,5 +1,8 @@
<template> <template>
<a :href="linkHref()" target="_blank" rel="noopener noreferrer">{{linkText()}}<OutboundLink/></a> <a :href="linkHref()" target="_blank" rel="noopener noreferrer">
{{linkText()}}
<OutboundLink/>
</a>
</template> </template>
<script> <script>
@ -25,14 +28,16 @@ var map = {
href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements" href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements"
}, },
"html-blocks": { "html-blocks": {
href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements" href:
"https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements"
}, },
"jsoup": { jsoup: {
displayName: "Jsoup", displayName: "Jsoup",
href: "https://github.com/jhy/jsoup/" href: "https://github.com/jhy/jsoup/"
}, },
"markwon-jsoup": { "markwon-jsoup": {
href: "https://github.com/noties/Markwon/tree/master/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup" href:
"https://github.com/noties/Markwon/tree/master/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup"
}, },
"commonmark-java": { "commonmark-java": {
href: "https://github.com/atlassian/commonmark-java/", href: "https://github.com/atlassian/commonmark-java/",

View File

@ -37,7 +37,7 @@ module.exports = {
'/docs/core/theme.md' '/docs/core/theme.md'
] ]
}, },
'/docs/ext-latex/latex.md', '/docs/ext-latex/',
'/docs/ext-strikethrough/strikethrough.md', '/docs/ext-strikethrough/strikethrough.md',
'/docs/ext-tables/tables.md', '/docs/ext-tables/tables.md',
'/docs/ext-tasklist/tasklist.md', '/docs/ext-tasklist/tasklist.md',

View File

@ -10,20 +10,27 @@ to learn how to add `Markwon` to your project
This is the most simple way to set markdown to a `TextView` or any of its siblings: This is the most simple way to set markdown to a `TextView` or any of its siblings:
```java ```java
Markwon.setMarkdown(textView, "**Hello there!**"); // obtain an instance of Markwon
final Markwon markwon = Markwon.create(context);
// set markdown
markwon.setMarkdown(textView, "**Hello there!**");
``` ```
The most simple way to obtain markdown to be applied _somewhere_ else: The most simple way to obtain markdown to be applied _somewhere_ else:
```java ```java
// parsed and styled markdown // obtain an instance of Markwon
final CharSequence markdown = Markwon.markdown(context, "**Hello there!**"); final Markwon markwon = Markwon.create(context);
// parse markdown and create styled text
final Spanned markdown = markwon.toMarkdown("**Hello there!**");
// use it // use it
Toast.makeText(context, markdown, Toast.LENGTH_LONG).show(); Toast.makeText(context, markdown, Toast.LENGTH_LONG).show();
``` ```
:::warning v3 migration :::warning 3.x.x migration
Starting with <Badge text="3.0.0" /> version Markwon no longer relies on static Starting with <Badge text="3.0.0" /> version Markwon no longer relies on static
utility methods. To learn more about migrating existing applications utility methods. To learn more about migrating existing applications
refer to [migration](/docs/migration-2-3.md) section. refer to [migration](/docs/migration-2-3.md) section.
@ -31,69 +38,78 @@ refer to [migration](/docs/migration-2-3.md) section.
## Longer one ## Longer one
When you need to customize markdown parsing/rendering you can use [SpannableConfiguration](/docs/configure.md): With explicit `parse` and `render` methods:
```java ```java
final SpannableConfiguration configuration = SpannableConfiguration.builder(context) // obtain an instance of Markwon
.asyncDrawableLoader(AsyncDrawableLoader.create()) final Markwon markwon = Markwon.create(context);
.build();
Markwon.setMarkdown(textView, configuration, "Are **you** still there?"); // parse markdown to commonmark-java Node
final Node node = markwon.parse("Are **you** still there?");
final CharSequence markdown = Markwon.markdown(configuration, "Are **you** still there?"); // create styled text from parsed Node
final Spanned markdown = markwon.render(node);
// use it on a TextView
markwon.setParsedMarkdown(textView, markdown);
// or a Toast
Toast.makeText(context, markdown, Toast.LENGTH_LONG).show(); Toast.makeText(context, markdown, Toast.LENGTH_LONG).show();
``` ```
## No magic one ## No magic one
In order to understand how previous examples work, let's break them down: So, what happens _internally_ when there is a `markwon#setMarkdown(TextView,String)` call?
Please note that this is mere representaion of what happens underneath and a caller
* construct a `Parser` (see: <Link name="commonmark-java" />) and parse markdown would likely never has to deal with these method calls directly. It still valuable
* construct a `SpannableConfiguration` (if it's not provided) to understand how things are working:
* *render* parsed markdown to Spannable (via `SpannableRenderer`)
* prepares TextView to display images, tables and links
* sets text
This flow answers the most simple usage of displaying markdown: one shot parsing
&amp; configuration of relatively small markdown chunks. If your markdown contains
a lot of text or you plan to display multiple UI widgets with markdown you might
consider *stepping in* and taking control of this flow.
The candidate requirements to *step in*:
* parsing and processing of parsed markdown in a background thread
* reusing `Parser` and/or `SpannableConfiguration` between multiple calls
* ignore images or tables specific logic (you know that markdown won't contain them)
So, if we expand `Markwon.setMarkdown(textView, markdown)` method we will see the following:
```java ```java
// create a Parser instance (can be done manually) // `Markwon#create` implicitly uses CorePlugin
// internally creates default Parser instance & registers `strike-through` & `tables` extension final Markwon markwon = Markwon.builder(context)
final Parser parser = Markwon.createParser(); .usePlugin(CorePlugin.create())
.build();
// core class to display markdown, can be obtained via this method, // each plugin will configure resulting Markwon instance
// which creates default instance (no images handling though), // we will cover it in plugins section of documentation
// or via `builder` method, which lets you to configure this instance
final SpannableConfiguration configuration = SpannableConfiguration.create(context);
final SpannableRenderer renderer = new SpannableRenderer(); // warning: pseudo-code
final Node node = parser.parse(markdown); // 0. each plugin will be called to _pre-process_ raw input markdown
final CharSequence text = renderer.render(configuration, node); rawInput = plugins.reduce(rawInput, (input, plugin) -> plugin.processMarkdown(input));
// for links in markdown to be clickable // 1. after input is processed it's being parsed to a Node
textView.setMovementMethod(LinkMovementMethod.getInstance()); node = parser.parse(rawInput);
// we need these due to the limited nature of Spannables to invalidate TextView // 2. each plugin will configure RenderProps
Markwon.unscheduleDrawables(textView); plugins.forEach(plugin -> plugin.configureRenderProps(renderProps));
Markwon.unscheduleTableRows(textView);
textView.setText(text); // 3. each plugin will be able to inspect or manipulate resulting Node
// before rendering
plugins.forEach(plugin -> plugin.beforeRender(node));
Markwon.scheduleDrawables(textView); // 4. node is being visited by a visitor
Markwon.scheduleTableRows(textView); node.accept(visitor);
// 5. each plugin will be called after node is being visited (aka rendered)
plugins.forEach(plugin -> plugin.afterRender(node, visitor));
// 6. styled markdown ready at this point
final Spanned markdown = visitor.markdown();
// 7. each plugin will be called before styled markdown is applied to a TextView
plugins.forEach(plugin -> plugin.beforeSetText(textView, markdown));
// 8. markdown is applied to a TextView
textView.setText(markdown);
// 9. each plugin will be called after markdown is applied to a TextView
plugins.forEach(plugin -> plugin.afterSetText(textView));
``` ```
As you can see a `plugin` is what lifts the most weight. We will cover
plugins next.
:::tip Note :::tip Note
If you are having trouble with `LinkMovementMethod` you can use If you are having trouble with `LinkMovementMethod` you can use
`Markwon.setText(textView, markdown, movementMethod)` method <Badge text="1.0.6" /> to specify _no_ movement `Markwon.setText(textView, markdown, movementMethod)` method <Badge text="1.0.6" /> to specify _no_ movement

View File

@ -19,7 +19,7 @@ $$\\text{A long division \\longdiv{12345}{13}$$
```java ```java
Markwon.builder(context) Markwon.builder(context)
.use(ImagesPlugin.create(context)) .use(ImagesPlugin.create(context))
.use(JLatexMathPlugin.create(new Config(textSize)) .use(JLatexMathPlugin.create(textSize))
.build(); .build();
``` ```
@ -30,17 +30,17 @@ final result
## Config ## Config
```java ```java
public static class Config { final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.create(context))
protected final float textSize; .usePlugin(JLatexMathPlugin.create(textSize, new BuilderConfigure() {
@Override
protected Drawable background; public void configureBuilder(@NonNull Builder builder) {
builder
@JLatexMathDrawable.Align .background(backgroundDrawable)
protected int align = JLatexMathDrawable.ALIGN_CENTER; .align(JLatexMathDrawable.ALIGN_CENTER)
.fitCanvas(true)
protected boolean fitCanvas = true; .padding(paddingPx);
protected int padding;
} }
}))
.build();
``` ```

View File

@ -2,11 +2,6 @@
# Getting started # Getting started
:::tip Installation
Please follow [installation](/docs/install.md) instructions
to learn how to add `Markwon` to your project
:::
## Quick one ## Quick one
This is the most simple way to set markdown to a `TextView` or any of its siblings: This is the most simple way to set markdown to a `TextView` or any of its siblings:

View File

@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.widget.TextView; import android.widget.TextView;
import org.commonmark.node.BlockQuote; import org.commonmark.node.BlockQuote;
@ -113,6 +114,16 @@ public class CorePlugin extends AbstractMarkwonPlugin {
OrderedListItemSpan.measure(textView, markdown); OrderedListItemSpan.measure(textView, markdown);
} }
@Override
public void afterSetText(@NonNull TextView textView) {
// let's ensure that there is a movement method applied
// we do it `afterSetText` so any user-defined movement method won't be
// replaced (it should be done in `beforeSetText` or manually on a TextView)
if (textView.getMovementMethod() == null) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
private static void text(@NonNull MarkwonVisitor.Builder builder) { private static void text(@NonNull MarkwonVisitor.Builder builder) {
builder.on(Text.class, new MarkwonVisitor.NodeVisitor<Text>() { builder.on(Text.class, new MarkwonVisitor.NodeVisitor<Text>() {
@Override @Override

View File

@ -1,47 +1,3 @@
# LaTeX # LaTeX
[![ext-latex](https://img.shields.io/maven-central/v/ru.noties.markwon/ext-latex.svg?label=ext-latex)](http://search.maven.org/#search|ga|1|g%3A%22ru.noties.markwon%22%20AND%20a%3A%22ext-latex%22) [Documentation](https://noties.github.io/Markwon/docs/ext-latex)
This is an extension that will help you display LaTeX formulas in your markdown.
Syntax is pretty simple: pre-fix and post-fix your latex with `$$` (double dollar sign).
`$$` should be the first characters in a line.
```markdown
$$
\\text{A long division \\longdiv{12345}{13}
$$
```
```markdown
$$\\text{A long division \\longdiv{12345}{13}$$
```
```java
Markwon.builder(context)
.use(ImagesPlugin.create(context))
.use(JLatexMathPlugin.create(new Config(textSize))
.build();
```
This extension uses [jlatexmath-android](https://github.com/noties/jlatexmath-android) artifact to create LaTeX drawable. Then it
registers special `latex` image scheme handler and uses `AsyncDrawableLoader` to display
final result
## Config
```java
public static class Config {
protected final float textSize;
protected Drawable background;
@JLatexMathDrawable.Align
protected int align = JLatexMathDrawable.ALIGN_CENTER;
protected boolean fitCanvas = true;
protected int padding;
}
```

View File

@ -9,7 +9,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dip" android:padding="8dip"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="15sp" android:textColor="#000"
android:textSize="16sp"
tools:text="whatever" /> tools:text="whatever" />
</ScrollView> </ScrollView>