Working with documentation
This commit is contained in:
parent
d91f367e0a
commit
18fd56a97c
@ -49,17 +49,20 @@ module.exports = {
|
||||
'/docs/core/configuration.md',
|
||||
'/docs/core/visitor.md',
|
||||
'/docs/core/spans-factory.md',
|
||||
'/docs/core/html-renderer.md'
|
||||
'/docs/core/html-renderer.md',
|
||||
'/docs/core/core-plugin.md',
|
||||
'/docs/core/movement-method-plugin.md'
|
||||
]
|
||||
},
|
||||
'/docs/ext-latex/',
|
||||
'/docs/ext-strikethrough/strikethrough.md',
|
||||
'/docs/ext-tables/tables.md',
|
||||
'/docs/ext-tasklist/tasklist.md',
|
||||
'/docs/ext-strikethrough/',
|
||||
'/docs/ext-tables/',
|
||||
'/docs/ext-tasklist/',
|
||||
{
|
||||
title: 'HTML',
|
||||
children: [
|
||||
'/docs/html/html.md'
|
||||
'/docs/html/',
|
||||
'/docs/html/custom-tag-handler.md'
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -70,8 +73,8 @@ module.exports = {
|
||||
'/docs/image/svg.md'
|
||||
]
|
||||
},
|
||||
'/docs/recycler/recycler.md',
|
||||
'/docs/syntax-highlight/syntax-highlight.md',
|
||||
'/docs/recycler/',
|
||||
'/docs/syntax-highlight/',
|
||||
'/docs/migration-2-3.md'
|
||||
]
|
||||
},
|
||||
|
@ -25,18 +25,19 @@ listed in <Link name="commonmark-spec" /> are supported (including support for *
|
||||
|
||||
* Emphasis (`*`, `_`)
|
||||
* Strong emphasis (`**`, `__`)
|
||||
* Strike-through (`~~`)
|
||||
* Headers (`#{1,6}`)
|
||||
* Links (`[]()` && `[][]`)
|
||||
* [Images](/docs/image-loader.md)
|
||||
* [Images](/docs/core/images.md)
|
||||
* Thematic break (`---`, `***`, `___`)
|
||||
* Quotes & nested quotes (`>{1,}`)
|
||||
* Ordered & non-ordered lists & nested ones
|
||||
* Inline code
|
||||
* Code blocks
|
||||
* Tables (*with limitations*)
|
||||
* [Syntax highlight](/docs/syntax-highlight.md)
|
||||
* [HTML](/docs/html.md)
|
||||
* [Strike-through](/docs/ext-strikethrough/) (`~~`)
|
||||
* [Tables](/docs/ext-tables/) (*with limitations*)
|
||||
* [Syntax highlight](/docs/syntax-highlight/)
|
||||
* [LaTeX](/docs/ext-latex/) formulas
|
||||
* [HTML](/docs/html/)
|
||||
* Emphasis (`<i>`, `<em>`, `<cite>`, `<dfn>`)
|
||||
* Strong emphasis (`<b>`, `<strong>`)
|
||||
* SuperScript (`<sup>`)
|
||||
@ -49,8 +50,8 @@ listed in <Link name="commonmark-spec" /> are supported (including support for *
|
||||
* Blockquote (`blockquote`)
|
||||
* Heading (`h1`, `h2`, `h3`, `h4`, `h5`, `h6`)
|
||||
* there is support to render any HTML tag, but it will require to create a special `TagHandler`,
|
||||
more information can be found in [HTML section](/docs/html.md#custom-tag-handler)
|
||||
* Task lists:
|
||||
more information can be found in [HTML section](/docs/html/custom-tag-handler.md)
|
||||
* [Task lists](/docs/ext-tasklist/):
|
||||
- [ ] Not _done_
|
||||
- [X] **Done** with `X`
|
||||
- [x] ~~and~~ **or** small `x`
|
||||
|
103
docs/docs/core/core-plugin.md
Normal file
103
docs/docs/core/core-plugin.md
Normal file
@ -0,0 +1,103 @@
|
||||
# Core plugin <Badge text="3.0.0" />
|
||||
|
||||
Since <Badge text="3.0.0" /> with introduction of _plugins_, Markwon
|
||||
**core** functionality was moved to a dedicated plugin.
|
||||
|
||||
```java
|
||||
CorePlugin.create();
|
||||
```
|
||||
|
||||
## Node visitors
|
||||
|
||||
`CorePlugin` registers these `commonmark-java` node visitors:
|
||||
* `Text`
|
||||
* `StrongEmphasis`
|
||||
* `Emphasis`
|
||||
* `BlockQuote`
|
||||
* `Code`
|
||||
* `FencedCodeBlock`
|
||||
* `IndentedCodeBlock`
|
||||
* `BulletList`
|
||||
* `OrderedList`
|
||||
* `ListItem`
|
||||
* `ThematicBreak`
|
||||
* `Heading`
|
||||
* `SoftLineBreak`
|
||||
* `HardLineBreak`
|
||||
* `Paragraph`
|
||||
* `Link`
|
||||
|
||||
## Span factories
|
||||
|
||||
`CorePlugin` adds these `SpanFactory`s:
|
||||
* `StrongEmphasis`
|
||||
* `Emphasis`
|
||||
* `BlockQuote`
|
||||
* `Code`
|
||||
* `FencedCodeBlock`
|
||||
* `IndentedCodeBlock`
|
||||
* `ListItem`
|
||||
* `Heading`
|
||||
* `Link`
|
||||
* `ThematicBreak`
|
||||
|
||||
|
||||
:::tip
|
||||
By default `CorePlugin` does not register a `Paragraph` `SpanFactory` but
|
||||
this can be done in your custom plugin:
|
||||
|
||||
```java
|
||||
Markwon.builder(context)
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
|
||||
builder.setFactory(Paragraph.class, (configuration, props) ->
|
||||
new ForegroundColorSpan(Color.RED));
|
||||
}
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
## Props
|
||||
These props are exported by `CorePlugin` and can be found in `CoreProps`:
|
||||
* `Prop<ListItemType> LIST_ITEM_TYPE` (BULLET | ORDERED)
|
||||
* `Prop<Integer> BULLET_LIST_ITEM_LEVEL`
|
||||
* `Prop<Integer> ORDERED_LIST_ITEM_NUMBER`
|
||||
* `Prop<Integer> HEADING_LEVEL`
|
||||
* `Prop<String> LINK_DESTINATION`
|
||||
* `Prop<Boolean> PARAGRAPH_IS_IN_TIGHT_LIST`
|
||||
|
||||
:::warning List item type
|
||||
Before <Badge text="3.0.0" /> `Markwon` had 2 distinct lists (bullet and ordered).
|
||||
Since <Badge text="3.0.0" /> a single `SpanFactory` is used, which internally checks
|
||||
for `Prop<ListItemType> LIST_ITEM_TYPE`.
|
||||
Beware of this if you would like to override only one of the list types. This is
|
||||
done to correspond to `commonmark-java` implementation.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
:::tip Soft line break
|
||||
Since <Badge text="3.0.0" /> Markwon core does not give an option to
|
||||
insert a new line when there is a soft line break in markdown. Instead a
|
||||
custom plugin can be used:
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(this)
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(SoftLineBreak.class, (visitor, softLineBreak) ->
|
||||
visitor.forceNewLine());
|
||||
}
|
||||
})
|
||||
.build();
|
||||
```
|
||||
:::
|
||||
|
||||
:::warning
|
||||
Please note that `CorePlugin` will implicitly set a `LinkMovementMethod` on a TextView
|
||||
if one is not present. If you wish to customize a MovementMethod that is used, apply
|
||||
one manually to a TextView (before applying markdown) or use the [MovementMethodPlugin](/docs/core/movement-method-plugin.md)
|
||||
which accepts a MovementMethod as an argument.
|
||||
:::
|
17
docs/docs/core/movement-method-plugin.md
Normal file
17
docs/docs/core/movement-method-plugin.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Movement method plugin
|
||||
|
||||
`MovementMethodPlugin` can be used to apply a `MovementMethod` to a TextView
|
||||
(important if you have links inside your markdown). By default `CorePlugin`
|
||||
will set a `LinkMovementMethod` on a TextView if one is missing. If you have
|
||||
specific needs for a `MovementMethod` and `LinkMovementMethod` doesn't answer
|
||||
your needs use `MovementMethodPlugin`:
|
||||
|
||||
```java
|
||||
Markwon.builder(context)
|
||||
.usePlugin(MovementMethodPlugin.create(ScrollingMovementMethod.getInstance()))
|
||||
```
|
||||
|
||||
:::tip
|
||||
If you are having trouble with system `LinkMovementMethod` as an alternative
|
||||
[BetterLinkMovementMethod](https://github.com/saket/Better-Link-Movement-Method) library can be used.
|
||||
:::
|
@ -24,6 +24,19 @@ final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(TablePlugin.create(tableTheme))
|
||||
```
|
||||
|
||||
```java
|
||||
Markwon.builder(context)
|
||||
.usePlugin(TablePlugin.create(builder ->
|
||||
builder
|
||||
.tableBorderColor(Color.RED)
|
||||
.tableBorderWidth(0)
|
||||
.tableCellPadding(0)
|
||||
.tableHeaderRowBackgroundColor(Color.BLACK)
|
||||
.tableEvenRowBackgroundColor(Color.GREEN)
|
||||
.tableOddRowBackgroundColor(Color.YELLOW)
|
||||
))
|
||||
```
|
||||
|
||||
Please note, that _by default_ tables have limitations. For example, there is no support
|
||||
for images inside table cells. And table contents won't be copied to clipboard if a TextView
|
||||
has such functionality. Table will always take full width of a TextView in which it is displayed.
|
1
docs/docs/html/custom-tag-handler.md
Normal file
1
docs/docs/html/custom-tag-handler.md
Normal file
@ -0,0 +1 @@
|
||||
# HTML custom tag handler
|
@ -50,18 +50,10 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
|
||||
@NonNull
|
||||
public static CorePlugin create() {
|
||||
return create(false);
|
||||
return new CorePlugin();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static CorePlugin create(boolean softBreakAddsNewLine) {
|
||||
return new CorePlugin(softBreakAddsNewLine);
|
||||
}
|
||||
|
||||
private final boolean softBreakAddsNewLine;
|
||||
|
||||
protected CorePlugin(boolean softBreakAddsNewLine) {
|
||||
this.softBreakAddsNewLine = softBreakAddsNewLine;
|
||||
protected CorePlugin() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,7 +70,7 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
listItem(builder);
|
||||
thematicBreak(builder);
|
||||
heading(builder);
|
||||
softLineBreak(builder, softBreakAddsNewLine);
|
||||
softLineBreak(builder);
|
||||
hardLineBreak(builder);
|
||||
paragraph(builder);
|
||||
link(builder);
|
||||
@ -341,15 +333,11 @@ public class CorePlugin extends AbstractMarkwonPlugin {
|
||||
});
|
||||
}
|
||||
|
||||
private static void softLineBreak(@NonNull MarkwonVisitor.Builder builder, final boolean softBreakAddsNewLine) {
|
||||
private static void softLineBreak(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(SoftLineBreak.class, new MarkwonVisitor.NodeVisitor<SoftLineBreak>() {
|
||||
@Override
|
||||
public void visit(@NonNull MarkwonVisitor visitor, @NonNull SoftLineBreak softLineBreak) {
|
||||
if (softBreakAddsNewLine) {
|
||||
visitor.ensureNewLine();
|
||||
} else {
|
||||
visitor.builder().append(' ');
|
||||
}
|
||||
visitor.builder().append(' ');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ public class MarkwonBuilderImplTest {
|
||||
};
|
||||
|
||||
// our subclass
|
||||
final CorePlugin corePlugin = new CorePlugin(false) {
|
||||
final CorePlugin corePlugin = new CorePlugin() {
|
||||
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,8 @@ package ru.noties.markwon.core;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.method.MovementMethod;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.BlockQuote;
|
||||
import org.commonmark.node.BulletList;
|
||||
@ -46,6 +48,7 @@ import ru.noties.markwon.SpannableBuilder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@ -223,26 +226,9 @@ public class CorePluginTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softbreak_adds_new_line_default() {
|
||||
// default is false
|
||||
softbreak_adds_new_line(CorePlugin.create(), false);
|
||||
}
|
||||
public void softbreak() {
|
||||
|
||||
@Test
|
||||
public void softbreak_adds_new_line_false() {
|
||||
// a space character will be added
|
||||
softbreak_adds_new_line(CorePlugin.create(false), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softbreak_adds_new_line_true() {
|
||||
// a new line will be added
|
||||
softbreak_adds_new_line(CorePlugin.create(true), true);
|
||||
}
|
||||
|
||||
private static void softbreak_adds_new_line(
|
||||
@NonNull CorePlugin plugin,
|
||||
boolean softBreakAddsNewLine) {
|
||||
final CorePlugin plugin = CorePlugin.create();
|
||||
|
||||
final MarkwonVisitor.Builder builder = mock(MarkwonVisitor.Builder.class);
|
||||
when(builder.on(any(Class.class), any(MarkwonVisitor.NodeVisitor.class))).thenReturn(builder);
|
||||
@ -259,21 +245,44 @@ public class CorePluginTest {
|
||||
final MarkwonVisitor.NodeVisitor<SoftLineBreak> nodeVisitor = captor.getValue();
|
||||
final MarkwonVisitor visitor = mock(MarkwonVisitor.class);
|
||||
|
||||
if (!softBreakAddsNewLine) {
|
||||
// we must mock SpannableBuilder and verify that it has a space character appended
|
||||
final SpannableBuilder spannableBuilder = mock(SpannableBuilder.class);
|
||||
when(visitor.builder()).thenReturn(spannableBuilder);
|
||||
nodeVisitor.visit(visitor, mock(SoftLineBreak.class));
|
||||
|
||||
// we must mock SpannableBuilder and verify that it has a space character appended
|
||||
final SpannableBuilder spannableBuilder = mock(SpannableBuilder.class);
|
||||
when(visitor.builder()).thenReturn(spannableBuilder);
|
||||
nodeVisitor.visit(visitor, mock(SoftLineBreak.class));
|
||||
verify(visitor, times(1)).builder();
|
||||
verify(spannableBuilder, times(1)).append(eq(' '));
|
||||
}
|
||||
|
||||
verify(visitor, times(1)).builder();
|
||||
verify(spannableBuilder, times(1)).append(eq(' '));
|
||||
@Test
|
||||
public void implicit_movement_method_after_set_text_added() {
|
||||
// validate that CorePlugin will implicitly add LinkMovementMethod if one is missing
|
||||
final TextView textView = mock(TextView.class);
|
||||
when(textView.getMovementMethod()).thenReturn(null);
|
||||
|
||||
} else {
|
||||
final CorePlugin plugin = CorePlugin.create();
|
||||
|
||||
nodeVisitor.visit(visitor, mock(SoftLineBreak.class));
|
||||
assertNull(textView.getMovementMethod());
|
||||
|
||||
verify(visitor, times(1)).ensureNewLine();
|
||||
}
|
||||
plugin.afterSetText(textView);
|
||||
|
||||
final ArgumentCaptor<MovementMethod> captor = ArgumentCaptor.forClass(MovementMethod.class);
|
||||
verify(textView, times(1)).setMovementMethod(captor.capture());
|
||||
|
||||
assertNotNull(captor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicit_movement_method_after_set_text_no_op() {
|
||||
// validate that CorePlugin won't change movement method if one is present on a TextView
|
||||
|
||||
final TextView textView = mock(TextView.class);
|
||||
when(textView.getMovementMethod()).thenReturn(mock(MovementMethod.class));
|
||||
|
||||
final CorePlugin plugin = CorePlugin.create();
|
||||
|
||||
plugin.afterSetText(textView);
|
||||
|
||||
verify(textView, times(0)).setMovementMethod(any(MovementMethod.class));
|
||||
}
|
||||
}
|
@ -73,7 +73,7 @@ abstract class BaseSuiteTest {
|
||||
@NonNull
|
||||
Markwon markwon() {
|
||||
return Markwon.builder(RuntimeEnvironment.application)
|
||||
.usePlugin(CorePlugin.create(softBreakAddsNewLine()))
|
||||
.usePlugin(CorePlugin.create())
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
|
||||
@ -99,10 +99,6 @@ abstract class BaseSuiteTest {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean softBreakAddsNewLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final Map<Class<? extends Node>, SpanFactory> CORE_NODES;
|
||||
|
||||
static {
|
||||
|
@ -1,39 +0,0 @@
|
||||
package ru.noties.markwon.core.suite;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import ru.noties.markwon.test.TestSpan.Document;
|
||||
|
||||
import static ru.noties.markwon.test.TestSpan.document;
|
||||
import static ru.noties.markwon.test.TestSpan.text;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class SoftBreakAddsNewLineTest extends BaseSuiteTest {
|
||||
|
||||
/*
|
||||
hello there!
|
||||
this one is on the next line
|
||||
hard break to the full extend
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
final Document document = document(
|
||||
text("hello there!\n"),
|
||||
text("this one is on the next line\n"),
|
||||
text("hard break to the full extend")
|
||||
);
|
||||
|
||||
matchInput("soft-break-adds-new-line.md", document);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean softBreakAddsNewLine() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -14,20 +14,15 @@ import static ru.noties.markwon.test.TestSpan.text;
|
||||
@Config(manifest = Config.NONE)
|
||||
public class SoftBreakTest extends BaseSuiteTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
final Document document = document(
|
||||
text("First line "),
|
||||
text("same line but with space between "),
|
||||
text("this is also the first line")
|
||||
);
|
||||
final Document document = document(
|
||||
text("First line "),
|
||||
text("same line but with space between "),
|
||||
text("this is also the first line")
|
||||
);
|
||||
|
||||
matchInput("soft-break.md", document);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean softBreakAddsNewLine() {
|
||||
return false;
|
||||
}
|
||||
matchInput("soft-break.md", document);
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public class PriorityProcessorTest {
|
||||
public void subclass_found() {
|
||||
// when a plugin comes after another, but _another_ was subclassed and placed in the list
|
||||
|
||||
final MarkwonPlugin core = new CorePlugin(false) {
|
||||
final MarkwonPlugin core = new CorePlugin() {
|
||||
};
|
||||
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
|
||||
@NonNull
|
||||
|
@ -30,6 +30,13 @@ public class TablePlugin extends AbstractMarkwonPlugin {
|
||||
void configureTheme(@NonNull TableTheme.Builder builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a {@link TablePlugin} with default {@link TableTheme} instance
|
||||
* (obtained via {@link TableTheme#create(Context)} method)
|
||||
*
|
||||
* @see #create(TableTheme)
|
||||
* @see #create(ThemeConfigure)
|
||||
*/
|
||||
@NonNull
|
||||
public static TablePlugin create(@NonNull Context context) {
|
||||
return new TablePlugin(TableTheme.create(context));
|
||||
|
@ -81,6 +81,8 @@ public class RecyclerActivity extends Activity {
|
||||
.usePlugin(CorePlugin.create())
|
||||
.usePlugin(ImagesPlugin.createWithAssets(context))
|
||||
.usePlugin(SvgPlugin.create(context.getResources()))
|
||||
// although we will be rendering table differently we still need
|
||||
// to register commonmark-java tables extension (which TablePlugin does)
|
||||
.usePlugin(TablePlugin.create(context))
|
||||
.usePlugin(HtmlPlugin.create())
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user