diff --git a/.travis.yml b/.travis.yml
index ec7e3e53..b77bdebc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,9 @@
# https://docs.travis-ci.com/user/languages/android/
+
language: android
+
+# so, out of blue travis requires this now (without it build would not even execute, immediate failure when downloading jdk)
+dist: trusty
jdk: openjdk8
sudo: false
diff --git a/docs/.vuepress/.artifacts.js b/docs/.vuepress/.artifacts.js
index 2f41fc13..a0f2a8de 100644
--- a/docs/.vuepress/.artifacts.js
+++ b/docs/.vuepress/.artifacts.js
@@ -1,4 +1,4 @@
// this is a generated file, do not modify. To update it run 'collectArtifacts.js' script
-const artifacts = [{"id":"core","name":"Core","group":"io.noties.markwon","description":"Core Markwon artifact that includes basic markdown parsing and rendering"},{"id":"ext-latex","name":"LaTeX","group":"io.noties.markwon","description":"Extension to add LaTeX formulas to Markwon markdown"},{"id":"ext-strikethrough","name":"Strikethrough","group":"io.noties.markwon","description":"Extension to add strikethrough markup to Markwon markdown"},{"id":"ext-tables","name":"Tables","group":"io.noties.markwon","description":"Extension to add tables markup (GFM) to Markwon markdown"},{"id":"ext-tasklist","name":"Task List","group":"io.noties.markwon","description":"Extension to add task lists (GFM) to Markwon markdown"},{"id":"html","name":"HTML","group":"io.noties.markwon","description":"Provides HTML parsing functionality"},{"id":"image","name":"Image","group":"io.noties.markwon","description":"Markwon image loading module (with optional GIF and SVG support)"},{"id":"image-gif","name":"Image GIF","group":"io.noties.markwon","description":"Adds GIF media support to Markwon markdown"},{"id":"image-glide","name":"Image Glide","group":"io.noties.markwon","description":"Markwon image loading module (based on Glide library)"},{"id":"image-okhttp","name":"Image OkHttp","group":"io.noties.markwon","description":"Adds OkHttp client to retrieve images data from network"},{"id":"image-picasso","name":"Image Picasso","group":"io.noties.markwon","description":"Markwon image loading module (based on Picasso library)"},{"id":"image-svg","name":"Image SVG","group":"io.noties.markwon","description":"Adds SVG media support to Markwon markdown"},{"id":"linkify","name":"Linkify","group":"io.noties.markwon","description":"Markwon plugin to linkify text (based on Android Linkify)"},{"id":"recycler","name":"Recycler","group":"io.noties.markwon","description":"Provides RecyclerView.Adapter to display Markwon markdown"},{"id":"recycler-table","name":"Recycler Table","group":"io.noties.markwon","description":"Provides MarkwonAdapter.Entry to render TableBlocks inside Android-native TableLayout widget"},{"id":"syntax-highlight","name":"Syntax Highlight","group":"io.noties.markwon","description":"Add syntax highlight to Markwon markdown via Prism4j library"}];
+const artifacts = [{"id":"core","name":"Core","group":"io.noties.markwon","description":"Core Markwon artifact that includes basic markdown parsing and rendering"},{"id":"ext-latex","name":"LaTeX","group":"io.noties.markwon","description":"Extension to add LaTeX formulas to Markwon markdown"},{"id":"ext-strikethrough","name":"Strikethrough","group":"io.noties.markwon","description":"Extension to add strikethrough markup to Markwon markdown"},{"id":"ext-tables","name":"Tables","group":"io.noties.markwon","description":"Extension to add tables markup (GFM) to Markwon markdown"},{"id":"ext-tasklist","name":"Task List","group":"io.noties.markwon","description":"Extension to add task lists (GFM) to Markwon markdown"},{"id":"html","name":"HTML","group":"io.noties.markwon","description":"Provides HTML parsing functionality"},{"id":"image","name":"Image","group":"io.noties.markwon","description":"Markwon image loading module (with optional GIF and SVG support)"},{"id":"image-glide","name":"Image Glide","group":"io.noties.markwon","description":"Markwon image loading module (based on Glide library)"},{"id":"image-picasso","name":"Image Picasso","group":"io.noties.markwon","description":"Markwon image loading module (based on Picasso library)"},{"id":"linkify","name":"Linkify","group":"io.noties.markwon","description":"Markwon plugin to linkify text (based on Android Linkify)"},{"id":"recycler","name":"Recycler","group":"io.noties.markwon","description":"Provides RecyclerView.Adapter to display Markwon markdown"},{"id":"recycler-table","name":"Recycler Table","group":"io.noties.markwon","description":"Provides MarkwonAdapter.Entry to render TableBlocks inside Android-native TableLayout widget"},{"id":"syntax-highlight","name":"Syntax Highlight","group":"io.noties.markwon","description":"Add syntax highlight to Markwon markdown via Prism4j library"}];
export { artifacts };
diff --git a/docs/.vuepress/components/MavenBadge4.vue b/docs/.vuepress/components/MavenBadge4.vue
new file mode 100644
index 00000000..4a8354cd
--- /dev/null
+++ b/docs/.vuepress/components/MavenBadge4.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 91f11d14..eaa57168 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -54,6 +54,17 @@ module.exports = {
'/docs/v4/core/render-props.md'
]
},
+ '/docs/v4/ext-latex/',
+ '/docs/v4/ext-strikethrough/',
+ '/docs/v4/ext-tables/',
+ '/docs/v4/ext-tasklist/',
+ '/docs/v4/html/',
+ '/docs/v4/image/',
+ '/docs/v4/image-glide/',
+ '/docs/v4/image-picasso/',
+ '/docs/v4/recycler/',
+ '/docs/v4/recycler-table/',
+ '/docs/v4/syntax-highlight/',
'/docs/v4/recipes.md',
'/docs/v4/migration-3-4.md'
],
diff --git a/docs/docs/v2/README.md b/docs/docs/v2/README.md
index 20275911..d237a0a1 100644
--- a/docs/docs/v2/README.md
+++ b/docs/docs/v2/README.md
@@ -7,6 +7,8 @@ title: 'Overview'
+
+
**Markwon** is a markdown library for Android. It parses markdown following
with the help of amazing library
and renders result as _Android-native_ Spannables. **No HTML** is involved
diff --git a/docs/docs/v2/configure.md b/docs/docs/v2/configure.md
index 4ba81749..48a973fc 100644
--- a/docs/docs/v2/configure.md
+++ b/docs/docs/v2/configure.md
@@ -1,5 +1,7 @@
# Configuration
+
+
`SpannableConfiguration` is the core component that controls how markdown is parsed and rendered.
It can be obtained via factory methods:
diff --git a/docs/docs/v2/factory.md b/docs/docs/v2/factory.md
index edf4a018..3ad083b0 100644
--- a/docs/docs/v2/factory.md
+++ b/docs/docs/v2/factory.md
@@ -1,5 +1,7 @@
# Factory
+
+
`SpannableFactory` is used to create Span implementations.
```java
diff --git a/docs/docs/v2/getting-started.md b/docs/docs/v2/getting-started.md
index 3361767a..f77b9ab9 100644
--- a/docs/docs/v2/getting-started.md
+++ b/docs/docs/v2/getting-started.md
@@ -1,5 +1,7 @@
# Getting started
+
+
## Quick one
This is the most simple way to set markdown to a `TextView` or any of its siblings:
diff --git a/docs/docs/v2/html.md b/docs/docs/v2/html.md
index 6130db36..8a6fc26d 100644
--- a/docs/docs/v2/html.md
+++ b/docs/docs/v2/html.md
@@ -1,5 +1,7 @@
# HTML
+
+
Starting with version `2.0.0` `Markwon` brings the whole HTML parsing/rendering
stack _on-site_. The main reason for this are _special_ definitions of HTML nodes
by . More specifically:
diff --git a/docs/docs/v2/image-loader.md b/docs/docs/v2/image-loader.md
index 6dca5991..68d1a881 100644
--- a/docs/docs/v2/image-loader.md
+++ b/docs/docs/v2/image-loader.md
@@ -1,5 +1,7 @@
# Images
+
+
By default `Markwon` doesn't handle images. Although `AsyncDrawable.Loader` is
defined in main artifact, it does not provide implementation.
diff --git a/docs/docs/v2/install.md b/docs/docs/v2/install.md
index efb9ef2a..d2edb82a 100644
--- a/docs/docs/v2/install.md
+++ b/docs/docs/v2/install.md
@@ -1,5 +1,7 @@
# Installation
+
+
In order to start using `Markwon` add this to your dependencies block
diff --git a/docs/docs/v2/syntax-highlight.md b/docs/docs/v2/syntax-highlight.md
index 854b82b0..a65e72f7 100644
--- a/docs/docs/v2/syntax-highlight.md
+++ b/docs/docs/v2/syntax-highlight.md
@@ -1,5 +1,7 @@
# Syntax highlight
+
+
This is a simple module to add **syntax highlight** functionality to your markdown rendered with `Markwon` library. It is based on [Prism4j](https://github.com/noties/Prism4j) so lead there to understand how to configure `Prism4j` instance.
diff --git a/docs/docs/v2/theme.md b/docs/docs/v2/theme.md
index 292e3e39..07aeb26d 100644
--- a/docs/docs/v2/theme.md
+++ b/docs/docs/v2/theme.md
@@ -1,5 +1,7 @@
# Theme
+
+
Here is the list of properties that can be configured via `SpannableTheme`. If you wish to control what
is out of this list, you can use [SpannableFactory](/docs/v2/factory.md)
abstraction which lets you to gather full control of Spans that are used to display markdown.
diff --git a/docs/docs/v2/view.md b/docs/docs/v2/view.md
index bd610344..c8489d94 100644
--- a/docs/docs/v2/view.md
+++ b/docs/docs/v2/view.md
@@ -1,5 +1,7 @@
# MarkwonView
+
+
This is simple library containing 2 views that are able to display markdown:
diff --git a/docs/docs/v4/ext-latex/README.md b/docs/docs/v4/ext-latex/README.md
new file mode 100644
index 00000000..4d57371f
--- /dev/null
+++ b/docs/docs/v4/ext-latex/README.md
@@ -0,0 +1,49 @@
+# LaTeX extension
+
+
+
+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(JLatexMathPlugin.create(textSize))
+ .build();
+```
+
+This extension uses [jlatexmath-android](https://github.com/noties/jlatexmath-android) artifact to create LaTeX drawable.
+
+## Config
+
+```java
+final Markwon markwon = Markwon.builder(context)
+ .usePlugin(JLatexMathPlugin.create(textSize, new BuilderConfigure() {
+ @Override
+ public void configureBuilder(@NonNull Builder builder) {
+ builder
+ .background(backgroundDrawable)
+ .align(JLatexMathDrawable.ALIGN_CENTER)
+ .fitCanvas(true)
+ .padding(paddingPx)
+ // @since 4.0.0 - optional, by default cached-thread-pool will be used
+ .executorService(Executors.newCachedThreadPool());
+ }
+ }))
+ .build();
+```
+
+
+:::tip
+Since `JLatexMathPlugin` operates independently of `ImagesPlugin`
+:::
\ No newline at end of file
diff --git a/docs/docs/v4/ext-strikethrough/README.md b/docs/docs/v4/ext-strikethrough/README.md
new file mode 100644
index 00000000..516b5b98
--- /dev/null
+++ b/docs/docs/v4/ext-strikethrough/README.md
@@ -0,0 +1,29 @@
+# Strikethrough extension
+
+
+
+This module adds `strikethrough` functionality to `Markwon` via `StrikethroughPlugin`:
+
+```java
+Markwon.builder(context)
+ .usePlugin(StrikethroughPlugin.create())
+```
+
+This plugin registers `SpanFactory` for `Strikethrough` node, so it's possible to customize Strikethrough Span that is used in rendering:
+
+```java
+Markwon.builder(context)
+ .usePlugin(StrikethroughPlugin.create())
+ .usePlugin(new AbstractMarkwonPlugin() {
+ @Override
+ public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
+ builder.setFactory(Strikethrough.class, new SpanFactory() {
+ @Override
+ public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
+ // will use Underline span instead of Strikethrough
+ return new UnderlineSpan();
+ }
+ });
+ }
+ })
+```
diff --git a/docs/docs/v4/ext-tables/README.md b/docs/docs/v4/ext-tables/README.md
new file mode 100644
index 00000000..04df9c5e
--- /dev/null
+++ b/docs/docs/v4/ext-tables/README.md
@@ -0,0 +1,99 @@
+# Tables extension
+
+
+
+This extension adds support for GFM tables.
+
+```java
+final Markwon markwon = Markwon.builder(context)
+ // create default instance of TablePlugin
+ .usePlugin(TablePlugin.create(context))
+```
+
+```java
+final TableTheme tableTheme = TableTheme.builder()
+ .tableBorderColor(Color.RED)
+ .tableBorderWidth(0)
+ .tableCellPadding(0)
+ .tableHeaderRowBackgroundColor(Color.BLACK)
+ .tableEvenRowBackgroundColor(Color.GREEN)
+ .tableOddRowBackgroundColor(Color.YELLOW)
+ .build();
+
+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.
+All columns will always be of the same width. So, _default_ implementation provides basic
+functionality which can answer some needs. These all come from the limited nature of the TextView
+to display such content.
+
+In order to provide full-fledged experience, tables must be displayed in a special widget.
+Since version `3.0.0` Markwon provides a special artifact `markwon-recycler` that allows
+to render markdown in a set of widgets in a RecyclerView. It also gives ability to change
+display widget form TextView to any other.
+
+```java
+final Table table = Table.parse(Markwon, TableBlock);
+myTableWidget.setTable(table);
+```
+
+:::tip
+To take advantage of this functionality and render tables without limitations (including
+horizontally scrollable layout when its contents exceed screen width), refer to [recycler-table](/docs/v3/recycler-table/)
+module documentation that adds support for rendering `TableBlock` markdown node inside Android-native `TableLayout` widget.
+:::
+
+## Theme
+
+### Cell padding
+
+Padding inside a table cell
+
+
+
+### Border color
+
+The color of table borders
+
+
+
+### Border width
+
+The width of table borders
+
+
+
+### Odd row background
+
+Background of an odd table row
+
+
+
+### Even row background
+
+Background of an even table row
+
+
+
+### Header row background
+
+Background of header table row
+
+
diff --git a/docs/docs/v4/ext-tasklist/README.md b/docs/docs/v4/ext-tasklist/README.md
new file mode 100644
index 00000000..154ec743
--- /dev/null
+++ b/docs/docs/v4/ext-tasklist/README.md
@@ -0,0 +1,146 @@
+# Task list extension
+
+
+
+Adds support for GFM (Github-flavored markdown) task-lists:
+
+```java
+Markwon.builder(context)
+ .usePlugin(TaskListPlugin.create(context));
+```
+
+---
+
+Create a default instance of `TaskListPlugin` with `TaskListDrawable` initialized to use
+`android.R.attr.textColorLink` as primary color and `android.R.attr.colorBackground` as background
+```java
+TaskListPlugin.create(context);
+```
+
+---
+
+Create an instance of `TaskListPlugin` with exact color values to use:
+```java
+// obtain color values
+final int checkedFillColor = /* */;
+final int normalOutlineColor = /* */;
+final int checkMarkColor = /* */;
+
+TaskListPlugin.create(checkedFillColor, normalOutlineColor, checkMarkColor);
+```
+
+---
+
+Specify own drawable for a task list item:
+
+```java
+// obtain drawable
+final Drawable drawable = /* */;
+
+TaskListPlugin.create(drawable);
+```
+
+:::warning
+Please note that custom drawable for a task list item must correctly handle state
+in order to display done/not-done:
+
+```java
+public class MyTaskListDrawable extends Drawable {
+
+ private boolean isChecked;
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ // draw accordingly to the isChecked value
+ }
+
+ /* implementation omitted */
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ final boolean isChecked = contains(state, android.R.attr.state_checked);
+ final boolean result = this.isChecked != isChecked;
+ if (result) {
+ this.isChecked = isChecked;
+ }
+ return result;
+ }
+
+ private static boolean contains(@Nullable int[] states, int value) {
+ if (states != null) {
+ for (int state : states) {
+ if (state == value) {
+ // NB return here
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+```
+:::
+
+## Task list mutation
+
+It is possible to mutate task list item state (toggle done/not-done). But note
+that `Markwon` won't handle state change internally by any means and this change
+is merely a visual one. If you need to persist state of a task list
+item change you have to implement it yourself. This should get your started:
+
+```java
+final Markwon markwon = Markwon.builder(context)
+ .usePlugin(TaskListPlugin.create(context))
+ .usePlugin(new AbstractMarkwonPlugin() {
+ @Override
+ public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
+
+ // obtain original SpanFactory set by TaskListPlugin
+ final SpanFactory origin = builder.getFactory(TaskListItem.class);
+ if (origin == null) {
+ // or throw, as it's a bit weird state and we expect
+ // this factory to be present
+ return;
+ }
+
+ builder.setFactory(TaskListItem.class, new SpanFactory() {
+ @Override
+ public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
+ // it's a bit non-secure behavior and we should validate
+ // the type of returned span first, but for the sake of brevity
+ // we skip this step
+ final TaskListSpan span = (TaskListSpan) origin.getSpans(configuration, props);
+
+ if (span == null) {
+ // or throw
+ return null;
+ }
+
+ // return an array of spans
+ return new Object[]{
+ span,
+ new ClickableSpan() {
+ @Override
+ public void onClick(@NonNull View widget) {
+ // toggle VISUAL state
+ span.setDone(!span.isDone());
+
+ // do not forget to invalidate widget
+ widget.invalidate();
+
+ // execute your persistence logic
+ }
+
+ @Override
+ public void updateDrawState(@NonNull TextPaint ds) {
+ // no-op, so appearance is not changed (otherwise
+ // task list item will look like a link)
+ }
+ }
+ };
+ }
+ });
+ }
+ })
+ .build();
+```
\ No newline at end of file
diff --git a/docs/docs/v4/html/README.md b/docs/docs/v4/html/README.md
new file mode 100644
index 00000000..44b95c54
--- /dev/null
+++ b/docs/docs/v4/html/README.md
@@ -0,0 +1,107 @@
+# HTML
+
+
+
+This artifact encapsulates HTML parsing from the core artifact and provides
+few predefined `TagHandlers`
+
+```java
+final Markwon markwon = Markwon.builder(context)
+ .usePlugin(HtmlPlugin.create())
+ .build();
+```
+
+As this artifact brings modified [jsoup](https://github.com/jhy/jsoup) library
+it was moved to a standalone module in order to minimize dependencies and unused code
+in applications that does not require HTML render capabilities.
+
+Before `Markwon` used android `Html` class for parsing and
+rendering. Unfortunately, according to markdown specification, markdown can contain
+HTML in _unpredictable_ way if rendered _outside_ of browser. For example:
+
+```markdown{4}
+
+Hello from italics tag
+
+bold>
+```
+
+This snippet could be represented as:
+* HtmlBlock (`\nHello from italics tag`)
+* HtmlInline (``)
+* HtmlInline (``)
+* Text (`bold`)
+* HtmlInline (``)
+
+:::tip A bit of background
+
+ had brought attention to differences between HTML & commonmark implementations.
+:::
+
+Unfortunately Android `HTML` class cannot parse a _fragment_ of HTML to later
+be included in a bigger set of content. This is why the decision was made to bring
+HTML parsing _in-markwon-house_
+
+## Predefined TagHandlers
+* ``
+* ``
+* `