diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee18c59a..655ae84d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
# 4.2.0-SNAPSHOT
* `MarkwonEditor` to highlight markdown input whilst editing (new module: `markwon-editor`)
+* `MarkwonInlineParser` to customize inline parsing (new module: `markwon-inline-parser`)
* `Markwon#configuration` method to expose `MarkwonConfiguration` via public API
* `HeadingSpan#getLevel` getter
* Add `SvgPictureMediaDecoder` in `image` module to deal with SVG without dimensions ([#165])
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index f8db7ba5..bd44aa90 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -104,6 +104,7 @@ module.exports = {
'/docs/v4/image/',
'/docs/v4/image-glide/',
'/docs/v4/image-picasso/',
+ '/docs/v4/inline-parser/',
'/docs/v4/linkify/',
'/docs/v4/recycler/',
'/docs/v4/recycler-table/',
diff --git a/docs/docs/v4/inline-parser/README.md b/docs/docs/v4/inline-parser/README.md
new file mode 100644
index 00000000..4c5471a1
--- /dev/null
+++ b/docs/docs/v4/inline-parser/README.md
@@ -0,0 +1,78 @@
+# Inline Parser
+
+**Experimental** commonmark-java inline parser that allows customizing
+core features and/or extend with own.
+
+Usage of _internal_ classes:
+```java
+import org.commonmark.internal.Bracket;
+import org.commonmark.internal.Delimiter;
+import org.commonmark.internal.ReferenceParser;
+import org.commonmark.internal.util.Escaping;
+import org.commonmark.internal.util.Html5Entities;
+import org.commonmark.internal.util.Parsing;
+import org.commonmark.internal.inline.AsteriskDelimiterProcessor;
+import org.commonmark.internal.inline.UnderscoreDelimiterProcessor;
+```
+
+---
+
+```java
+// all default (like current commonmark-java InlineParserImpl)
+final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
+ .includeDefaults()
+ .build();
+```
+
+```java
+// disable images (current markdown images will be considered as links):
+final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
+ .includeDefaults()
+ .excludeInlineProcessor(BangInlineProcessor.class)
+ .build();
+```
+
+```java
+// disable core delimiter processors for `*`|`_` and `**`|`__`
+final InlineParserFactory factory = MarkwonInlineParser.factoryBuilder()
+ .includeDefaults()
+ .excludeDelimiterProcessor(AsteriskDelimiterProcessor.class)
+ .excludeDelimiterProcessor(UnderscoreDelimiterProcessor.class)
+ .build();
+```
+
+```java
+// disable _all_ markdown inlines except for links (open and close bracket handling `[` & `]`)
+final InlineParserFactory inlineParserFactory = MarkwonInlineParser.factoryBuilder()
+ // note that there is no `includeDefaults` method call
+ .referencesEnabled(true)
+ .addInlineProcessor(new OpenBracketInlineProcessor())
+ .addInlineProcessor(new CloseBracketInlineProcessor())
+ .build();
+```
+
+To use custom InlineParser:
+```java
+final Markwon markwon = Markwon.builder(this)
+ .usePlugin(new AbstractMarkwonPlugin() {
+ @Override
+ public void configureParser(@NonNull Parser.Builder builder) {
+ builder.inlineParserFactory(inlineParserFactory);
+ }
+ })
+ .build();
+```
+
+---
+
+The list of available inline processors:
+
+* `AutolinkInlineProcessor` (`<` => ``)
+* `BackslashInlineProcessor` (`\\`)
+* `BackticksInlineProcessor` (`
=> `code`
)
+* `BangInlineProcessor` (`!` => ``)
+* `CloseBracketInlineProcessor` (`]` => `[link](#href)`, ``)
+* `EntityInlineProcessor` (`&` => `&`)
+* `HtmlInlineProcessor` (`<` => ``)
+* `NewLineInlineProcessor` (`\n`)
+* `OpenBracketInlineProcessor` (`[` => `[link](#href)`)
\ No newline at end of file
diff --git a/markwon-inline-parser/README.md b/markwon-inline-parser/README.md
index 5b0e1335..bcfa3802 100644
--- a/markwon-inline-parser/README.md
+++ b/markwon-inline-parser/README.md
@@ -4,17 +4,13 @@
```java
import org.commonmark.internal.Bracket;
+import org.commonmark.internal.Delimiter;
+import org.commonmark.internal.ReferenceParser;
import org.commonmark.internal.util.Escaping;
import org.commonmark.internal.util.Html5Entities;
import org.commonmark.internal.util.Parsing;
-import org.commonmark.internal.Bracket;
-import org.commonmark.internal.Delimiter;
-import org.commonmark.internal.ReferenceParser;
import org.commonmark.internal.inline.AsteriskDelimiterProcessor;
import org.commonmark.internal.inline.UnderscoreDelimiterProcessor;
-import org.commonmark.internal.util.Escaping;
-import org.commonmark.internal.Bracket;
-import org.commonmark.internal.Delimiter;
```
`StaggeredDelimiterProcessor` class source is copied (required for InlineParser)
\ No newline at end of file
diff --git a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/AsteriskDelimiterProcessor.java b/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/AsteriskDelimiterProcessor.java
deleted file mode 100644
index 3a8d570e..00000000
--- a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/AsteriskDelimiterProcessor.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.noties.markwon.inlineparser;
-
-/**
- * @since 4.2.0-SNAPSHOT
- */
-public class AsteriskDelimiterProcessor extends org.commonmark.internal.inline.AsteriskDelimiterProcessor {
-}
diff --git a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/MarkwonInlineParser.java b/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/MarkwonInlineParser.java
index 5bdda362..89bb18c5 100644
--- a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/MarkwonInlineParser.java
+++ b/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/MarkwonInlineParser.java
@@ -6,6 +6,8 @@ import androidx.annotation.Nullable;
import org.commonmark.internal.Bracket;
import org.commonmark.internal.Delimiter;
import org.commonmark.internal.ReferenceParser;
+import org.commonmark.internal.inline.AsteriskDelimiterProcessor;
+import org.commonmark.internal.inline.UnderscoreDelimiterProcessor;
import org.commonmark.internal.util.Escaping;
import org.commonmark.node.Link;
import org.commonmark.node.Node;
diff --git a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/UnderscoreDelimiterProcessor.java b/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/UnderscoreDelimiterProcessor.java
deleted file mode 100644
index 83f7771f..00000000
--- a/markwon-inline-parser/src/main/java/io/noties/markwon/inlineparser/UnderscoreDelimiterProcessor.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.noties.markwon.inlineparser;
-
-/**
- * @since 4.2.0-SNAPSHOT
- */
-public class UnderscoreDelimiterProcessor extends org.commonmark.internal.inline.UnderscoreDelimiterProcessor {
-}
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 6bc6ef02..ee887f8c 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -33,6 +33,8 @@
android:name=".editor.EditorActivity"
android:windowSoftInputMode="adjustResize" />
+
+
\ No newline at end of file
diff --git a/sample/src/main/java/io/noties/markwon/sample/MainActivity.java b/sample/src/main/java/io/noties/markwon/sample/MainActivity.java
index 59c6049f..db937d19 100644
--- a/sample/src/main/java/io/noties/markwon/sample/MainActivity.java
+++ b/sample/src/main/java/io/noties/markwon/sample/MainActivity.java
@@ -24,6 +24,7 @@ import io.noties.markwon.sample.customextension.CustomExtensionActivity;
import io.noties.markwon.sample.customextension2.CustomExtensionActivity2;
import io.noties.markwon.sample.editor.EditorActivity;
import io.noties.markwon.sample.html.HtmlActivity;
+import io.noties.markwon.sample.inlineparser.InlineParserActivity;
import io.noties.markwon.sample.latex.LatexActivity;
import io.noties.markwon.sample.precomputed.PrecomputedActivity;
import io.noties.markwon.sample.recycler.RecyclerActivity;
@@ -122,6 +123,10 @@ public class MainActivity extends Activity {
activity = EditorActivity.class;
break;
+ case INLINE_PARSER:
+ activity = InlineParserActivity.class;
+ break;
+
default:
throw new IllegalStateException("No Activity is associated with sample-item: " + item);
}
diff --git a/sample/src/main/java/io/noties/markwon/sample/Sample.java b/sample/src/main/java/io/noties/markwon/sample/Sample.java
index c2a2add3..221ee0bc 100644
--- a/sample/src/main/java/io/noties/markwon/sample/Sample.java
+++ b/sample/src/main/java/io/noties/markwon/sample/Sample.java
@@ -23,7 +23,9 @@ public enum Sample {
PRECOMPUTED_TEXT(R.string.sample_precomputed_text),
- EDITOR(R.string.sample_editor);
+ EDITOR(R.string.sample_editor),
+
+ INLINE_PARSER(R.string.sample_inline_parser);
private final int textResId;
diff --git a/sample/src/main/java/io/noties/markwon/sample/inlineparser/InlineParserActivity.java b/sample/src/main/java/io/noties/markwon/sample/inlineparser/InlineParserActivity.java
new file mode 100644
index 00000000..955d6db2
--- /dev/null
+++ b/sample/src/main/java/io/noties/markwon/sample/inlineparser/InlineParserActivity.java
@@ -0,0 +1,119 @@
+package io.noties.markwon.sample.inlineparser;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.commonmark.node.Block;
+import org.commonmark.node.BlockQuote;
+import org.commonmark.node.Heading;
+import org.commonmark.node.HtmlBlock;
+import org.commonmark.node.ListBlock;
+import org.commonmark.node.ThematicBreak;
+import org.commonmark.parser.InlineParserFactory;
+import org.commonmark.parser.Parser;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import io.noties.markwon.AbstractMarkwonPlugin;
+import io.noties.markwon.Markwon;
+import io.noties.markwon.inlineparser.BackticksInlineProcessor;
+import io.noties.markwon.inlineparser.CloseBracketInlineProcessor;
+import io.noties.markwon.inlineparser.MarkwonInlineParser;
+import io.noties.markwon.inlineparser.OpenBracketInlineProcessor;
+import io.noties.markwon.sample.R;
+
+public class InlineParserActivity extends Activity {
+
+ private TextView textView;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_text_view);
+
+ this.textView = findViewById(R.id.text_view);
+
+// links_only();
+
+ disable_code();
+ }
+
+ private void links_only() {
+
+ // create an inline-parser-factory that will _ONLY_ parse links
+ // this would mean:
+ // * no emphasises (strong and regular aka bold and italics),
+ // * no images,
+ // * no code,
+ // * no HTML entities (&)
+ // * no HTML tags
+ // markdown blocks are still parsed
+ final InlineParserFactory inlineParserFactory = MarkwonInlineParser.factoryBuilder()
+ .referencesEnabled(true)
+ .addInlineProcessor(new OpenBracketInlineProcessor())
+ .addInlineProcessor(new CloseBracketInlineProcessor())
+ .build();
+
+ final Markwon markwon = Markwon.builder(this)
+ .usePlugin(new AbstractMarkwonPlugin() {
+ @Override
+ public void configureParser(@NonNull Parser.Builder builder) {
+ builder.inlineParserFactory(inlineParserFactory);
+ }
+ })
+ .build();
+
+ // note that image is considered a link now
+ final String md = "**bold_bold-italic_** html-u, [link](#)  `code`";
+ markwon.setMarkdown(textView, md);
+ }
+
+ private void disable_code() {
+ // parses all as usual, but ignores code (inline and block)
+
+ final InlineParserFactory inlineParserFactory = MarkwonInlineParser.factoryBuilder()
+ .includeDefaults()
+ .excludeInlineProcessor(BackticksInlineProcessor.class)
+ .build();
+
+ // unfortunately there is no _exclude_ method for parser-builder
+ final Set> enabledBlocks = new HashSet>() {{
+ // IndentedCodeBlock.class and FencedCodeBlock.class are missing
+ // this is full list (including above) that can be passed to `enabledBlockTypes` method
+ addAll(Arrays.asList(
+ BlockQuote.class,
+ Heading.class,
+ HtmlBlock.class,
+ ThematicBreak.class,
+ ListBlock.class));
+ }};
+
+ final Markwon markwon = Markwon.builder(this)
+ .usePlugin(new AbstractMarkwonPlugin() {
+ @Override
+ public void configureParser(@NonNull Parser.Builder builder) {
+ builder
+ .inlineParserFactory(inlineParserFactory)
+ .enabledBlockTypes(enabledBlocks);
+ }
+ })
+ .build();
+
+ final String md = "# Head!\n\n" +
+ "* one\n" +
+ "+ two\n\n" +
+ "and **bold** to `you`!\n\n" +
+ "> a quote _em_\n\n" +
+ "```java\n" +
+ "final int i = 0;\n" +
+ "```\n\n" +
+ "**Good day!**";
+ markwon.setMarkdown(textView, md);
+ }
+}
diff --git a/sample/src/main/res/values/strings-samples.xml b/sample/src/main/res/values/strings-samples.xml
index 7cf55ed2..a26f62c5 100644
--- a/sample/src/main/res/values/strings-samples.xml
+++ b/sample/src/main/res/values/strings-samples.xml
@@ -27,4 +27,6 @@
# \# Editor\n\n`MarkwonEditor` sample usage to highlight user input in EditText
+ # \# Inline Parser\n\nUsage of custom inline parser
+
\ No newline at end of file