Implicit LinkMovementMethod if not supplied explicitly
This commit is contained in:
parent
ba5bb9bfc7
commit
02e7539881
@ -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) {
|
||||||
|
@ -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/",
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
|
||||||
& 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
|
||||||
|
@ -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();
|
||||||
```
|
```
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -1,47 +1,3 @@
|
|||||||
# LaTeX
|
# 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;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user