Working with documentation v4
This commit is contained in:
parent
8b0edc32c3
commit
8944f39592
@ -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
|
||||
|
||||
|
@ -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 };
|
||||
|
24
docs/.vuepress/components/MavenBadge4.vue
Normal file
24
docs/.vuepress/components/MavenBadge4.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<a :href="mavenSearchUrl()"><img :src="shieldImgageUrl()" :alt="displayLabel"></a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MavenBadge',
|
||||
props: ['artifact', 'label'],
|
||||
methods: {
|
||||
mavenSearchUrl: function() {
|
||||
return `http://search.maven.org/#search|ga|1|g%3A%22io.noties.markwon%22%20AND%20a%3A%22${this.artifact}%22`;
|
||||
},
|
||||
shieldImgageUrl: function() {
|
||||
return `https://img.shields.io/maven-central/v/io.noties.markwon/${this.artifact}.svg?label=${this.displayLabel}`;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayLabel() {
|
||||
return this.label || this.artifact;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -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'
|
||||
],
|
||||
|
@ -7,6 +7,8 @@ title: 'Overview'
|
||||
<br><br>
|
||||
<MavenBadges2xx/>
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
**Markwon** is a markdown library for Android. It parses markdown following
|
||||
<Link name="commonmark-spec" /> with the help of amazing <Link name="commonmark-java" /> library
|
||||
and renders result as _Android-native_ Spannables. **No HTML** is involved
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Configuration
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
`SpannableConfiguration` is the core component that controls how markdown is parsed and rendered.
|
||||
It can be obtained via factory methods:
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Factory <Badge text="1.1.0" />
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
`SpannableFactory` is used to create Span implementations.
|
||||
|
||||
```java
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Getting started
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
## Quick one
|
||||
|
||||
This is the most simple way to set markdown to a `TextView` or any of its siblings:
|
||||
|
@ -1,5 +1,7 @@
|
||||
# HTML <Badge text="2.0.0" />
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
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 <Link name="commonmark-spec" />. More specifically: <Link name="commonmark-spec#inline" displayName="inline" />
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Images
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
By default `Markwon` doesn't handle images. Although `AsyncDrawable.Loader` is
|
||||
defined in main artifact, it does not provide implementation.
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Installation
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
<MavenBadges2xx />
|
||||
|
||||
In order to start using `Markwon` add this to your dependencies block
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Syntax highlight
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
<MavenBadge2xx artifact="markwon-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.
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Theme
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
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.
|
||||
|
@ -1,5 +1,7 @@
|
||||
# MarkwonView
|
||||
|
||||
<LegacyWarning />
|
||||
|
||||
<MavenBadge2xx artifact="markwon-view" />
|
||||
|
||||
This is simple library containing 2 views that are able to display markdown:
|
||||
|
49
docs/docs/v4/ext-latex/README.md
Normal file
49
docs/docs/v4/ext-latex/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# LaTeX extension
|
||||
|
||||
<MavenBadge4 :artifact="'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(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 <Badge text="4.0.0" /> `JLatexMathPlugin` operates independently of `ImagesPlugin`
|
||||
:::
|
29
docs/docs/v4/ext-strikethrough/README.md
Normal file
29
docs/docs/v4/ext-strikethrough/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Strikethrough extension
|
||||
|
||||
<MavenBadge4 :artifact="'ext-strikethrough'" />
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
```
|
99
docs/docs/v4/ext-tables/README.md
Normal file
99
docs/docs/v4/ext-tables/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Tables extension
|
||||
|
||||
<MavenBadge4 :artifact="'ext-tables'" />
|
||||
|
||||
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
|
||||
|
||||
<ThemeProperty name="tableCellPadding" type="@Px int" defaults="0" />
|
||||
|
||||
### Border color
|
||||
|
||||
The color of table borders
|
||||
|
||||
<ThemeProperty name="tableBorderColor" type="@ColorInt int" defaults="(text color) with 75 (0-255) alpha" />
|
||||
|
||||
### Border width
|
||||
|
||||
The width of table borders
|
||||
|
||||
<ThemeProperty name="tableBorderWidth" type="@Px int" defaults="Stroke with of context TextPaint" />
|
||||
|
||||
### Odd row background
|
||||
|
||||
Background of an odd table row
|
||||
|
||||
<ThemeProperty name="tableOddRowBackgroundColor" type="@ColorInt int" defaults="(text color) with 22 (0-255) alpha" />
|
||||
|
||||
### Even row background <Badge text="1.1.1" />
|
||||
|
||||
Background of an even table row
|
||||
|
||||
<ThemeProperty name="tableEventRowBackgroundColor" type="@ColorInt int" defaults="0" />
|
||||
|
||||
### Header row background <Badge text="1.1.1" />
|
||||
|
||||
Background of header table row
|
||||
|
||||
<ThemeProperty name="tableHeaderRowBackgroundColor" type="@ColorInt int" defaults="0" />
|
146
docs/docs/v4/ext-tasklist/README.md
Normal file
146
docs/docs/v4/ext-tasklist/README.md
Normal file
@ -0,0 +1,146 @@
|
||||
# Task list extension
|
||||
|
||||
<MavenBadge4 :artifact="'ext-tasklist'" />
|
||||
|
||||
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();
|
||||
```
|
107
docs/docs/v4/html/README.md
Normal file
107
docs/docs/v4/html/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
# HTML
|
||||
|
||||
<MavenBadge4 :artifact="'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 <Badge text="2.0.0" /> `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}
|
||||
<i>
|
||||
Hello from italics tag
|
||||
|
||||
</i><b>bold></b>
|
||||
```
|
||||
|
||||
This snippet could be represented as:
|
||||
* HtmlBlock (`<i>\nHello from italics tag`)
|
||||
* HtmlInline (`<i>`)
|
||||
* HtmlInline (`<b>`)
|
||||
* Text (`bold`)
|
||||
* HtmlInline (`</b>`)
|
||||
|
||||
:::tip A bit of background
|
||||
<br>
|
||||
<GithubIssue id="52" displayName="This issue" /> had brought attention to differences between HTML & commonmark implementations. <br><br>
|
||||
:::
|
||||
|
||||
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
|
||||
* `<img>`
|
||||
* `<a>`
|
||||
* `<blockquote>`
|
||||
* `<sub>`
|
||||
* `<sup>`
|
||||
* `<b>, <strong>`
|
||||
* `<s>, <del>`
|
||||
* `<u>, <ins>`
|
||||
* `<ul>, <ol>`
|
||||
* `<i>, <cite>, <em>, <dfn>`
|
||||
* `<h1>, <h2>, <h3>, <h4>, <h5>, <h6>`
|
||||
|
||||
:::tip
|
||||
All predefined tag handlers will use styling spans for native markdown content.
|
||||
So, if your `Markwon` instance was configured to, for example, render Emphasis
|
||||
nodes as a <span style="color: #FF0000">red text</span> then HTML tag handler will
|
||||
use the same span. This includes images, links, UrlResolver, LinkProcessor, etc
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
Staring with <Badge text="4.0.0" /> you can exclude all default tag handlers:
|
||||
|
||||
```java
|
||||
.usePlugin(HtmlPlugin.create(new HtmlPlugin.HtmlConfigure() {
|
||||
@Override
|
||||
public void configureHtml(@NonNull HtmlPlugin plugin) {
|
||||
plugin.excludeDefaults(true);
|
||||
}
|
||||
}))
|
||||
```
|
||||
|
||||
or via plugin:
|
||||
|
||||
```java
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configure(@NonNull Registry registry) {
|
||||
registry.require(HtmlPlugin.class, new Action<HtmlPlugin>() {
|
||||
@Override
|
||||
public void apply(@NonNull HtmlPlugin htmlPlugin) {
|
||||
htmlPlugin.excludeDefaults(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If you wish to exclude some of them `TagHandlerNoOp` can be used:
|
||||
|
||||
```java
|
||||
.usePlugin(HtmlPlugin.create(new HtmlPlugin.HtmlConfigure() {
|
||||
@Override
|
||||
public void configureHtml(@NonNull HtmlPlugin plugin) {
|
||||
plugin.addHandler(TagHandlerNoOp.create("h4", "h5", "h6", "img"));
|
||||
}
|
||||
}))
|
||||
```
|
||||
|
||||
## TagHandler
|
||||
|
||||
|
3
docs/docs/v4/image-glide/README.md
Normal file
3
docs/docs/v4/image-glide/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Image Glide
|
||||
|
||||
<MavenBadge4 :artifact="'image-glide'" />
|
3
docs/docs/v4/image-picasso/README.md
Normal file
3
docs/docs/v4/image-picasso/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Image Picasso
|
||||
|
||||
<MavenBadge4 :artifact="'image-picasso'" />
|
172
docs/docs/v4/image/README.md
Normal file
172
docs/docs/v4/image/README.md
Normal file
@ -0,0 +1,172 @@
|
||||
# Image
|
||||
|
||||
<MavenBadge4 :artifact="'image'" />
|
||||
|
||||
In order to display images in your markdown `ImagesPlugin` can be used.
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(ImagesPlugin.create())
|
||||
```
|
||||
|
||||
:::tip
|
||||
There are also modules that add image loading capabilities to markdown
|
||||
based on image-loading libraries: [image-glide](/docs/v4/image-glide/) and
|
||||
[image-picasso](/docs/v4/image-picasso/)
|
||||
:::
|
||||
|
||||
`ImagesPlugin` splits the image-loading into 2 parts: scheme-handling and media-decoding.
|
||||
|
||||
## SchemeHandler
|
||||
|
||||
To add a scheme-handler to `ImagesPlugin`:
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(ImagesPlugin.create())
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configure(@NonNull Registry registry) {
|
||||
registry.require(ImagesPlugin.class, new Action<ImagesPlugin>() {
|
||||
@Override
|
||||
public void apply(@NonNull ImagesPlugin imagesPlugin) {
|
||||
imagesPlugin.addSchemeHandler(DataUriSchemeHandler.create());
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||
@Override
|
||||
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||
plugin.addSchemeHandler(DataUriSchemeHandler.create());
|
||||
}
|
||||
}))
|
||||
```
|
||||
|
||||
`ImagesPlugin` comes with a set of predefined scheme-handlers:
|
||||
* `FileSchemeHandler` - `file://`
|
||||
* `DataUriSchemeHandler` - `data:`
|
||||
* `NetworkSchemeHandler` - `http`, `https`
|
||||
* `OkHttpNetworkSchemeHandler` - `http`, `https`
|
||||
|
||||
### FileSchemeHandler
|
||||
|
||||
Loads images via `file://` scheme. Allows loading images from `assets` folder.
|
||||
|
||||
```java
|
||||
// default implementation, no assets handling
|
||||
FileSchemeHandler.create();
|
||||
|
||||
// assets loading
|
||||
FileSchemeHandler.createWithAssets(context);
|
||||
```
|
||||
|
||||
:::warning
|
||||
Assets loading will work when your URL will include `android_asset` the the path,
|
||||
for example: `file:///android_asset/image.png` (mind the 3 slashes `///`). If you wish
|
||||
to _assume_ all images without proper scheme to point to assets folder, then you can use
|
||||
[UrlProcessorAndroidAssets](/docs/v4/core/configuration.html#urlprocessorandroidassets)
|
||||
:::
|
||||
|
||||
By default `ImagesPlugin` includes _plain_ `FileSchemeHandler` (without assets support),
|
||||
so if you wish to change that you can explicitly specify it:
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||
@Override
|
||||
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||
plugin.addSchemeHandler(FileSchemeHandler.createWithAssets(context));
|
||||
}
|
||||
}))
|
||||
```
|
||||
|
||||
### DataUriSchemeHandler
|
||||
`DataUriSchemeHandler` allows _inlining_ images with `data:` scheme (`data:image/svg+xml;base64,MTIz`).
|
||||
This scheme-handler is registered by default, so you do not need to add it explicitly.
|
||||
|
||||
### NetworkSchemeHandler
|
||||
`NetworkSchemeHandler` allows obtaining images from `http://` and `https://` uris
|
||||
(internally it uses `HttpURLConnection`). This scheme-handler is registered by default
|
||||
|
||||
### OkHttpNetworkSchemeHandler
|
||||
`OkHttpNetworkSchemeHandler` allows obtaining images from `http://` and `https://` uris
|
||||
via [okhttp library](https://github.com/square/okhttp). Please note that in order to use
|
||||
this scheme-handler you must explicitly add `okhttp` library to your project.
|
||||
|
||||
```java
|
||||
// default instance
|
||||
OkHttpNetworkSchemeHandler.create();
|
||||
|
||||
// specify OkHttpClient to use
|
||||
OkHttpNetworkSchemeHandler.create(new OkHttpClient());
|
||||
|
||||
// @since 4.0.0
|
||||
OkHttpNetworkSchemeHandler.create(Call.Factory);
|
||||
```
|
||||
|
||||
### Custom SchemeHandler
|
||||
|
||||
```java
|
||||
public abstract class SchemeHandler {
|
||||
|
||||
@NonNull
|
||||
public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri);
|
||||
|
||||
@NonNull
|
||||
public abstract Collection<String> supportedSchemes();
|
||||
}
|
||||
```
|
||||
|
||||
Starting with <Badge text="4.0.0" /> `SchemeHandler` can return a result (when no
|
||||
further decoding is required):
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||
@Override
|
||||
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||
// for example to return a drawable resource
|
||||
plugin.addSchemeHandler(new SchemeHandler() {
|
||||
@NonNull
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
final int resourceId = context.getResources().getIdentifier(
|
||||
raw.substring("resources://".length()),
|
||||
"drawable",
|
||||
context.getPackageName());
|
||||
|
||||
// it's fine if it throws, async-image-loader will catch exception
|
||||
final Drawable drawable = context.getDrawable(resourceId);
|
||||
|
||||
// it's important to apply bounds to resulting drawable
|
||||
DrawableUtils.applyIntrinsicBounds(drawable);
|
||||
|
||||
return ImageItem.withResult(drawable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Collection<String> supportedSchemes() {
|
||||
return Collections.singleton("resources");
|
||||
}
|
||||
});
|
||||
}
|
||||
}))
|
||||
```
|
||||
|
||||
:::tip
|
||||
If you are using [html](/docs/v4/html/) you do not have to additionally setup
|
||||
images displayed via `<img>` tag, as `HtmlPlugin` automatically uses configured
|
||||
image loader. But images referenced in HTML come with additional support for
|
||||
sizes, which is not supported natively by markdown, allowing absolute or relative sizes:
|
||||
|
||||
```html
|
||||
<img src="./assets/my-image" width="100%">
|
||||
```
|
||||
:::
|
@ -1,3 +1,53 @@
|
||||
# Recipes
|
||||
|
||||
todo
|
||||
|
||||
## SpannableFactory
|
||||
|
||||
Consider using `NoCopySpannableFactory` when a `TextView` will be used to display markdown
|
||||
multiple times (for example in a `RecyclerView`):
|
||||
|
||||
```java
|
||||
// call after inflation and before setting markdown
|
||||
textView.setSpannableFactory(NoCopySpannableFactory.getInstance());
|
||||
```
|
||||
|
||||
|
||||
## Autolink
|
||||
|
||||
Do not use `autolink` XML attribute on your `TextView` as it will remove all links except autolinked ones.
|
||||
Consider using [linkify plugin](/docs/v4/linkify.md) or commonmark-java [autolink extension](https://github.com/atlassian/commonmark-java)
|
||||
|
||||
|
||||
|
||||
## Custom typeface
|
||||
|
||||
When using a custom typeface on a `TextView` you might find that **bold** and *italic* nodes
|
||||
are displayed incorrectly. Consider registering own `SpanFactories` for `StrongEmphasis` and `Emphasis` nodes:
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
|
||||
builder
|
||||
.setFactory(StrongEmphasis.class, new SpanFactory() {
|
||||
@Override
|
||||
public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
|
||||
return new StyleSpan(Typeface.BOLD);
|
||||
}
|
||||
})
|
||||
.setFactory(Emphasis.class, new SpanFactory() {
|
||||
@Override
|
||||
public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) {
|
||||
return new StyleSpan(Typeface.ITALIC);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.build();
|
||||
```
|
||||
|
||||
Please check that `StyleSpan` works for you. If it doesn't consider
|
||||
using `CustomTypefaceSpan` with your typeface directly.
|
||||
|
||||
|
||||
|
92
docs/docs/v4/recycler-table/README.md
Normal file
92
docs/docs/v4/recycler-table/README.md
Normal file
@ -0,0 +1,92 @@
|
||||
# Recycler Table <Badge text="3.0.0" />
|
||||
|
||||
<MavenBadge4 :artifact="'recycler-table'" />
|
||||
|
||||
Artifact that provides [MarkwonAdapter.Entry](/docs/v3/recycler/) to render `TableBlock` inside
|
||||
Android-native `TableLayout` widget.
|
||||
|
||||
<img :src="$withBase('/assets/recycler-table-screenshot.png')" alt="screenshot" width="45%">
|
||||
<br>
|
||||
<small><em><sup>*</sup> It's possible to wrap `TableLayout` inside a `HorizontalScrollView` to include all table content</em></small>
|
||||
|
||||
---
|
||||
|
||||
Register instance of `TableEntry` with `MarkwonAdapter` to render TableBlocks:
|
||||
```java
|
||||
final MarkwonAdapter adapter = MarkwonAdapter.builder(R.layout.adapter_default_entry, R.id.text)
|
||||
.include(TableBlock.class, TableEntry.create(builder -> builder
|
||||
.tableLayout(R.layout.adapter_table_block, R.id.table_layout)
|
||||
.textLayoutIsRoot(R.layout.view_table_entry_cell)))
|
||||
.build();
|
||||
```
|
||||
|
||||
`TableEntry` requires at least 2 arguments:
|
||||
* `tableLayout` - layout with `TableLayout` inside
|
||||
* `textLayout` - layout with `TextView` inside (represents independent table cell)
|
||||
|
||||
In case when required view is the root of layout specific builder methods can be used:
|
||||
* `tableLayoutIsRoot(int)`
|
||||
* `textLayoutIsRoot(int)`
|
||||
|
||||
If your layouts have different structure (for example wrap a `TableView` inside a `HorizontalScrollView`)
|
||||
then you should use methods that accept ID of required view inside layout:
|
||||
* `tableLayout(int, int)`
|
||||
* `textLayout(int, int)`
|
||||
|
||||
---
|
||||
|
||||
To display `TableBlock` as a `TableLayout` specific `MarkwonPlugin` must be used: `TableEntryPlugin`.
|
||||
|
||||
:::warning
|
||||
Do not use `TablePlugin` if you wish to display markdown tables via `TableEntry`. Use **TableEntryPlugin** instead
|
||||
:::
|
||||
|
||||
`TableEntryPlugin` can reuse existing `TablePlugin` to make appearance of tables the same in both contexts:
|
||||
when rendering _natively_ in a TextView and when rendering in RecyclerView with TableEntry.
|
||||
|
||||
* `TableEntryPlugin.create(Context)` - creates plugin with default `TableTheme`
|
||||
* `TableEntryPlugin.create(TableTheme)` - creates plugin with provided `TableTheme`
|
||||
* `TableEntryPlugin.create(TablePlugin.ThemeConfigure)` - creates plugin with theme configured by `ThemeConfigure`
|
||||
* `TableEntryPlugin.create(TablePlugin)` - creates plugin with `TableTheme` used in provided `TablePlugin`
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(TableEntryPlugin.create(context))
|
||||
// other plugins
|
||||
.build();
|
||||
```
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(TableEntryPlugin.create(builder -> builder
|
||||
.tableBorderWidth(0)
|
||||
.tableHeaderRowBackgroundColor(Color.RED)))
|
||||
// other plugins
|
||||
.build();
|
||||
```
|
||||
|
||||
## Table with scrollable content
|
||||
|
||||
To stretch table columns to fit the width of screen or to make table scrollable when content exceeds screen width
|
||||
this layout can be used:
|
||||
|
||||
```xml
|
||||
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingRight="16dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:scrollbarStyle="outsideInset">
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/table_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:stretchColumns="*" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
```
|
153
docs/docs/v4/recycler/README.md
Normal file
153
docs/docs/v4/recycler/README.md
Normal file
@ -0,0 +1,153 @@
|
||||
# Recycler <Badge text="3.0.0" />
|
||||
|
||||
<MavenBadge4 :artifact="'recycler'" />
|
||||
|
||||
This artifact allows displaying markdown in a set of Android widgets
|
||||
inside a RecyclerView. Can be useful when displaying lengthy markdown
|
||||
content or **displaying certain markdown blocks inside specific widgets**.
|
||||
|
||||
```java
|
||||
// create an adapter that will use a TextView for each block of markdown
|
||||
// `createTextViewIsRoot` accepts a layout in which TextView is the root view
|
||||
final MarkwonAdapter adapter =
|
||||
MarkwonAdapter.createTextViewIsRoot(R.layout.adapter_default_entry);
|
||||
```
|
||||
|
||||
```java
|
||||
// `create` method accepts a layout with TextView and ID of a TextView
|
||||
// which allows wrapping a TextView inside another widget or combine with other widgets
|
||||
final MarkwonAdapter adapter =
|
||||
MarkwonAdapter.create(R.layout.adapter_default_entry, R.id.text_view);
|
||||
|
||||
// initialize RecyclerView (LayoutManager, Decorations, etc)
|
||||
final RecyclerView recyclerView = obtainRecyclerView();
|
||||
|
||||
// set adapter
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
// obtain an instance of Markwon (register all required plugins)
|
||||
final Markwon markwon = obtainMarkwon();
|
||||
|
||||
// set markdown to be displayed
|
||||
adapter.setMarkdown(markwon, "# This is markdown!");
|
||||
|
||||
// NB, adapter does not handle updates on its own, please use
|
||||
// whatever method appropriate for you.
|
||||
adapter.notifyDataSetChanged();
|
||||
```
|
||||
|
||||
Initialized adapter above will use a TextView for each markdown block.
|
||||
In order to tell adapter to render certain blocks differently a `builder` can be used.
|
||||
For example, let's render `FencedCodeBlock` inside a `HorizontalScrollView`:
|
||||
|
||||
```java
|
||||
// we still need to have a _default_ entry
|
||||
final MarkwonAdapter adapter =
|
||||
MarkwonAdapter.builderTextViewIsRoot(R.layout.adapter_default_entry)
|
||||
.include(FencedCodeBlock.class, new FencedCodeBlockEntry())
|
||||
.build();
|
||||
```
|
||||
|
||||
where `FencedCodeBlockEntry` is:
|
||||
|
||||
```java
|
||||
public class FencedCodeBlockEntry extends MarkwonAdapter.Entry<FencedCodeBlock, FencedCodeBlockEntry.Holder> {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Holder createHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
|
||||
return new Holder(inflater.inflate(R.layout.adapter_fenced_code_block, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindHolder(@NonNull Markwon markwon, @NonNull Holder holder, @NonNull FencedCodeBlock node) {
|
||||
markwon.setParsedMarkdown(holder.textView, markwon.render(node));
|
||||
}
|
||||
|
||||
public static class Holder extends MarkwonAdapter.Holder {
|
||||
|
||||
final TextView textView;
|
||||
|
||||
public Holder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
||||
this.textView = requireView(R.id.text_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
and its layout (`R.layout.adapter_fenced_code_block`):
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingRight="16dip"
|
||||
android:scrollbarStyle="outsideInset">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#0f000000"
|
||||
android:fontFamily="monospace"
|
||||
android:lineSpacingExtra="2dip"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingRight="16dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
```
|
||||
|
||||
As we apply styling to `FencedCodeBlock` _manually_, we no longer need
|
||||
`Markwon` to apply styling spans for us, so `Markwon` initialization could be:
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
// your other plugins
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) {
|
||||
builder.on(FencedCodeBlock.class, (visitor, fencedCodeBlock) -> {
|
||||
// we actually won't be applying code spans here, as our custom view will
|
||||
// draw background and apply mono typeface
|
||||
//
|
||||
// NB the `trim` operation on literal (as code will have a new line at the end)
|
||||
final CharSequence code = visitor.configuration()
|
||||
.syntaxHighlight()
|
||||
.highlight(fencedCodeBlock.getInfo(), fencedCodeBlock.getLiteral().trim());
|
||||
visitor.builder().append(code);
|
||||
});
|
||||
}
|
||||
})
|
||||
.build();
|
||||
```
|
||||
|
||||
Previously we have created a `FencedCodeBlockEntry` but all it does is apply markdown to a TextView.
|
||||
For such a case there is a `SimpleEntry` that could be used instead:
|
||||
|
||||
```java
|
||||
final MarkwonAdapter adapter =
|
||||
MarkwonAdapter.builderTextViewIsRoot(R.layout.adapter_default_entry)
|
||||
.include(FencedCodeBlock.class, SimpleEntry.create(R.layout.adapter_fenced_code_block, R.id.text_view))
|
||||
.build();
|
||||
```
|
||||
|
||||
:::tip
|
||||
`SimpleEntry` also takes care of _caching_ parsed markdown. So each node will be
|
||||
parsed only once and each subsequent adapter binding call will reuse previously cached markdown.
|
||||
:::
|
||||
|
||||
:::tip Tables
|
||||
There is a standalone artifact that adds support for displaying markdown tables
|
||||
natively via `TableLayout`. Please refer to its [documentation](/docs/v3/recycler-table/)
|
||||
:::
|
74
docs/docs/v4/syntax-highlight/README.md
Normal file
74
docs/docs/v4/syntax-highlight/README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Syntax highlight
|
||||
|
||||
<MavenBadge4 :artifact="'syntax-highlight'" />
|
||||
|
||||
This is a 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.
|
||||
|
||||
<img :src="$withBase('/art/markwon-syntax-default.png')" alt="theme-default" width="80%">
|
||||
|
||||
|
||||
<img :src="$withBase('/art/markwon-syntax-darkula.png')" alt="theme-darkula" width="80%">
|
||||
|
||||
---
|
||||
|
||||
First, we need to obtain an instance of `Prism4jSyntaxHighlight` which implements Markwon's `SyntaxHighlight`:
|
||||
|
||||
```java
|
||||
final SyntaxHighlight highlight =
|
||||
Prism4jSyntaxHighlight.create(Prism4j, Prism4jTheme);
|
||||
```
|
||||
|
||||
we also can obtain an instance of `Prism4jSyntaxHighlight` that has a _fallback_ option (if a language is not defined in `Prism4j` instance, fallback language can be used):
|
||||
|
||||
```java
|
||||
final SyntaxHighlight highlight =
|
||||
Prism4jSyntaxHighlight.create(Prism4j, Prism4jTheme, String);
|
||||
```
|
||||
|
||||
Generally obtaining a `Prism4j` instance is pretty easy:
|
||||
|
||||
```java
|
||||
final Prism4j prism4j = new Prism4j(new GrammarLocatorDef());
|
||||
```
|
||||
|
||||
Where `GrammarLocatorDef` is a generated grammar locator (if you use `prism4j-bundler` annotation processor)
|
||||
|
||||
`Prism4jTheme` is a specific type that is defined in this module (`prism4j` doesn't know anything about rendering). It has 2 implementations:
|
||||
|
||||
* `Prism4jThemeDefault`
|
||||
* `Prism4jThemeDarkula`
|
||||
|
||||
Both of them can be obtained via factory method `create`:
|
||||
|
||||
* `Prism4jThemeDefault.create()`
|
||||
* `Prism4jThemeDarkula.create()`
|
||||
|
||||
But of cause nothing is stopping you from defining your own theme:
|
||||
|
||||
```java
|
||||
public interface Prism4jTheme {
|
||||
|
||||
@ColorInt
|
||||
int background();
|
||||
|
||||
@ColorInt
|
||||
int textColor();
|
||||
|
||||
void apply(
|
||||
@NonNull String language,
|
||||
@NonNull Prism4j.Syntax syntax,
|
||||
@NonNull SpannableStringBuilder builder,
|
||||
int start,
|
||||
int end
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
You can extend `Prism4jThemeBase` which has some helper methods
|
||||
:::
|
||||
|
||||
```java
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(SyntaxHighlightPlugin.create(prism4j, prism4jTheme))
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user