From 8b8bf60290a4daba4d2cc74a9cefa6f42c7783cc Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Tue, 21 Aug 2018 16:48:42 +0300 Subject: [PATCH] Working with documentation --- app/src/main/java/ru/noties/markwon/Blah.java | 21 ++ .../ru/noties/markwon/MarkdownRenderer.java | 2 +- .../art => art}/markwon-syntax-darkula.png | Bin .../art => art}/markwon-syntax-default.png | Bin docs/.vuepress/components/Link.vue | 7 + docs/.vuepress/config.js | 5 + docs/.vuepress/style.styl | 0 docs/README.md | 53 +++- docs/docs/configure.md | 227 +++++++++++++++++- docs/docs/factory.md | 15 +- docs/docs/getting-started.md | 91 +++++++ docs/docs/html.md | 2 +- docs/docs/image-loader.md | 153 +++++++++++- docs/docs/install.md | 75 +++++- docs/docs/syntax-highlight.md | 66 ++++- docs/docs/theme.md | 74 +++++- docs/package-lock.json | 5 + docs/package.json | 1 + markwon-syntax-highlight/README.md | 4 +- 19 files changed, 775 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/ru/noties/markwon/Blah.java rename {markwon-syntax-highlight/art => art}/markwon-syntax-darkula.png (100%) rename {markwon-syntax-highlight/art => art}/markwon-syntax-default.png (100%) create mode 100644 docs/.vuepress/style.styl diff --git a/app/src/main/java/ru/noties/markwon/Blah.java b/app/src/main/java/ru/noties/markwon/Blah.java new file mode 100644 index 00000000..f77fc2b8 --- /dev/null +++ b/app/src/main/java/ru/noties/markwon/Blah.java @@ -0,0 +1,21 @@ +package ru.noties.markwon; + +import android.content.res.Resources; + +import ru.noties.markwon.il.AsyncDrawableLoader; +import ru.noties.markwon.il.GifMediaDecoder; +import ru.noties.markwon.il.ImageMediaDecoder; +import ru.noties.markwon.il.SvgMediaDecoder; + +public class Blah { + + static { +AsyncDrawableLoader.builder() + .mediaDecoders( +SvgMediaDecoder.create(Resources), +GifMediaDecoder.create(boolean), +ImageMediaDecoder.create(Resources) + ) +.build(); + } +} diff --git a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java index d8e8a83d..133290a1 100644 --- a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java +++ b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java @@ -96,7 +96,7 @@ public class MarkdownRenderer { .theme(SpannableTheme.builderWithDefaults(context) .codeBackgroundColor(background) .codeTextColor(prism4jTheme.textColor()) - .listItemColor(red) + .codeMultilineMargin(100) .build()) .factory(new GifAwareSpannableFactory(gifPlaceholder)) .trimWhiteSpaceEnd(false) diff --git a/markwon-syntax-highlight/art/markwon-syntax-darkula.png b/art/markwon-syntax-darkula.png similarity index 100% rename from markwon-syntax-highlight/art/markwon-syntax-darkula.png rename to art/markwon-syntax-darkula.png diff --git a/markwon-syntax-highlight/art/markwon-syntax-default.png b/art/markwon-syntax-default.png similarity index 100% rename from markwon-syntax-highlight/art/markwon-syntax-default.png rename to art/markwon-syntax-default.png diff --git a/docs/.vuepress/components/Link.vue b/docs/.vuepress/components/Link.vue index 68967153..07e549ef 100644 --- a/docs/.vuepress/components/Link.vue +++ b/docs/.vuepress/components/Link.vue @@ -14,6 +14,9 @@ var map = { "commonmark-spec#block": { href: "https://spec.commonmark.org/0.28/#html-blocks" }, + "commonmark-spec#soft-break": { + href: "https://spec.commonmark.org/0.28/#soft-line-breaks" + }, "commonmark-dingus": { displayName: "commonmark dingus", href: "https://spec.commonmark.org/dingus/" @@ -30,6 +33,10 @@ var map = { }, "markwon-jsoup": { href: "https://github.com/noties/Markwon/tree/master/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup" + }, + "commonmark-java": { + href: "https://github.com/atlassian/commonmark-java/", + displayName: "commonmark-java" } }; diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 8b763ead..ea62ff75 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -22,5 +22,10 @@ module.exports = { '/docs/html.md', '/docs/view.md' ] + }, + markdown: { + config: md => { + md.use(require('markdown-it-task-lists')); + } } } \ No newline at end of file diff --git a/docs/.vuepress/style.styl b/docs/.vuepress/style.styl new file mode 100644 index 00000000..e69de29b diff --git a/docs/README.md b/docs/README.md index c90358f4..f3b6a87b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,9 +7,8 @@ title: 'Overview'

-**Markwon** is a markdown library for Android. It parses markdown -following [commonmark spec] with the help -of amazing [commonmark-java](https://github.com/atlassian/commonmark-java/) library +**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 as an intermediate step. **No WebView** is required. It's extremely fast, feature-rich and extensible. @@ -21,4 +20,50 @@ but also gives all the means to tweak the appearance if desired. All markdown fe listed in [commonmark spec] are supported (including support for **inlined/block HTML code**, **markdown tables**, **images** and **syntax highlight**). -[commonmark spec]: https://spec.commonmark.org/ \ No newline at end of file +## Supported markdown features: + +* Emphasis (`*`, `_`) +* Strong emphasis (`**`, `__`) +* Strike-through (`~~`) +* Headers (`#{1,6}`) +* Links (`[]()` && `[][]`) +* [Images](/docs/image-loader.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) + * Emphasis (``, ``, ``, ``) + * Strong emphasis (``, ``) + * SuperScript (``) + * SubScript (``) + * Underline (``, `ins`) + * Strike-through (``, ``, ``) + * Link (`a`) + * Lists (`ul`, `ol`) + * Images (`img` will require configured image loader) + * Blockquote (`blockquote`) + * there is support to render any HTML tags, 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: +- [ ] Not _done_ + - [X] **Done** with `X` + - [x] ~~and~~ **or** small `x` + +## Screenshots + +screenshot light #1 +screenshot light #2 +screenshot light #3 +screenshot dark #2 + +By default configuration uses TextView textColor for styling, so changing textColor changes style + +:::tip Sample application +Screenshots are taken from sample application. It is a generic markdown viewer +with support to display markdown content via `http`, `https` & `file` schemes +and 2 themes included: Light & Dark. It can be downloaded from [releases](https://github.com/noties/Markwon/releases) +::: diff --git a/docs/docs/configure.md b/docs/docs/configure.md index 6ceba05b..aa638a6d 100644 --- a/docs/docs/configure.md +++ b/docs/docs/configure.md @@ -1,42 +1,245 @@ # Configuration -factories -basic info -there are a lot of options, but using default instance will probably fit the needs (except maybe for image loader) +`SpannableConfiguration` is the core component that controls how markdown is parsed and rendered. +It can be obtained via factory methods: + +```java +// creates default implementation +final SpannableConfiguration configuration = SpannableConfiguration.create(context); +``` + +```java +// creates configurablable instance via `#builder` method +final SpannableConfiguration configuration = SpannableConfiguration.builder(context) + .asyncDrawableLoader(AsyncDrawableLoader.create()) + .build(); +``` + +:::tip Note +If `#builder` factory method is used, you do not need to specify default +values as they will be applied automatically +::: + +:::warning Images +If you plan on using images inside your markdown/HTML, you will have to **explicitly** +register an implementation of `AsyncDrawable.Loader` via `#asyncDrawableLoader` builder method. +`Markwon` comes with ready implementation for that and it can be cound in +`markwon-image-loader` module. Refer to module [documentation](/docs/image-loader.md) +::: ## Theme +`SpannableTheme` controls how markdown is rendered. It has pretty extensive number of +options that can be found [here](/docs/theme.md) + +```java +SpannableConfiguration.builder(context) + .theme(SpannableTheme) + .build(); +``` + +If `SpannableTheme` is not provided explicitly, `SpannableTheme.create(context)` will be used + ## Images ### Async loader +`AsyncDrawable.Loader` handles images in your markdown and HTML + +```java +SpannableConfiguration.builder(context) + .asyncDrawableLoader(AsyncDrawable.Loader) + .build(); +``` + +If `AsyncDrawable.Loader` is not provided explicitly, default **no-op** implementation will be used. + +:::tip Implementation +There are no restrictions on what implementation to use, but `Markwon` has artifact that can +answer the most common needs of displaying SVG, GIF and other image formats. It can be found [here](/docs/image-loader.md) +::: + ### Size resolver +`ImageSizeResolver` controls the size of an image to be displayed. Currently it +handles only HTML images (specified via `img` tag). + +```java +SpannableConfiguration.builder(context) + .imageSizeResolver(ImageSizeResolver) + .build(); +``` + +If not provided explicitly, default `ImageSizeResolverDef` implementation will be used. +It handles 3 dimention units: +* `%` (percent) +* `em` (relative to text size) +* `px` (absolute size, every dimention that is not `%` or `em` is considered to be _absolute_) + +```html + + + +``` + +`ImageSizeResolverDef` keeps the ratio of original image if one of the dimentions is missing. + +:::warning Height% +There is no support for `%` units for `height` dimention. This is due to the fact that +height of an TextView in which markdown is displayed is non-stable and changes with time +(for example when image is loaded and applied to a TextView it will _increase_ TextView's height), +so we will have no point-of-refence from which to _calculate_ image height. +::: + ## Syntax highlight -Although interface was there initially only starting with {version} there is an implementation -refer to doc +`SyntaxHighlight` controls the syntax highlight for code blocks (in markdown). + +```java +SpannableConfiguration.builder(context) + .syntaxHighlight(SyntaxHighlight) + .build(); +``` + +If not provided explicitly, default **no-op** implementation will be used. + +:::tip Syntax highlight +Although `SyntaxHighlight` interface was included with the very first version +of `Markwon` there were no ready-to-use implementations. But starting with +`Markwon` provides one. It can be found in `markwon-syntax-highlight` artifact. Refer +to module [documentation](/docs/syntax-highlight.md) +::: ## Link resolver -Interface to respond to action when a link span is clicked +`LinkSpan.Resolver` is triggered when a link is clicked in markdown/HTML. + +```java +SpannableConfiguration.builder(context) + .linkResolver(LinkSpan.Resolver) + .build(); +``` + +If not provided explicitly, default `LinkResolverDef` implementation will be used. +Underneath it constructs an `Intent` and _tries_ to start an Activity associated with it. +It no Activity is found, it will silently fail (no runtime exceptions) ## URL processor -Interface to pre-process all URLs in a document (assets, relative, absolute) +`UrlProcessor` is used to process found URLs in markdown/HTML. + +```java +SpannableConfiguration.builder(context) + .urlProcessor(UrlProcessor) + .build(); +``` + +If not provided explicitly, default **no-op** implementation will be used. + +`Markwon` provides 2 implementations of `UrlProcessor`: +* `UrlProcessorRelativeToAbsolute` +* `UrlProcessorAndroidAssets` + +### UrlProcessorRelativeToAbsolute + +`UrlProcessorRelativeToAbsolute` can be used to make relative URL absolute. For example if an image is +defined like this: `![img](./art/image.JPG)` and `UrlProcessorRelativeToAbsolute` +is created with `https://github.com/noties/Markwon/raw/master/` as the base: +`new UrlProcessorRelativeToAbsolute("https://github.com/noties/Markwon/raw/master/")`, +then final image will have `https://github.com/noties/Markwon/raw/master/art/image.JPG` +as the destination. + +### UrlProcessorAndroidAssets + +`UrlProcessorAndroidAssets` can be used to make processed links to point to Android assets folder. +So an image: `![img](./art/image.JPG)` will have `file:///android_asset/art/image.JPG` as the +destination ## Factory -## softBreakAddsNewLine -issue, reason +`SpannableFactory` is used to control _what_ span implementations to be used -## trimWhiteSpaceEnd -compact mode +```java +SpannableConfiguration.builder(context) + .factory(SpannableFactory) + .build(); +``` + +If not provided explicitly, default `SpannableFactoryDef` implementation will be used. It is documented +in [this section](/docs/factory.md) + +## Soft line break + +`softBreakAddsNewLine` option controls how _soft breaks_ are treated in the final result. +If `true` -> soft break will add a new line, else it will add a ` ` (space) char. + +```java +SpannableConfiguration.builder(context) + .softBreakAddsNewLine(boolean) + .build(); +``` + +If not provided explicitly, default `false` value will be used. + + + +## Trim white space from end + +`trimWhiteSpaceEnd` option controls whether or not to trim white spaces from the +end of a document. + +```java +SpannableConfiguration.builder(context) + .trimWhiteSpaceEnd(boolean) + .build(); +``` + +If not provided explicitly, default `true` value will be used. + +:::tip Before +Before `2.0.0` version this functionality was _implicitly_ included in +`SpannableBuilder#text` method. This is no longer true and now `SpannableBuilder` +does not trim white spaces (which was by default and non-configurable) +::: ## HTML ### Parser +`MarkwonHtmlParser` is used to parse HTML content + +```java +SpannableConfiguration.builder(context) + .htmlParser(MarkwonHtmlParser) + .build(); +``` + +if not provided explicitly, default `MarkwonHtmlParserImpl` will be used +**if** it can be found in classpath, otherwise default **no-op** implementation +wiil be used. Refer to [HTML](/docs/html.md#parser) document for more information about this behavior. + ### Renderer -### htmlIgnoreNonClosedTags +`MarkwonHtmlRenderer` controls how parsed HTML content will be rendered. + +```java +SpannableConfiguration.builder(context) + .htmlRenderer(MarkwonHtmlRenderer) + .build(); +``` + +If not provided explicitly, default `MarkwonHtmlRenderer` implementation will be used. +It is documented [here](/docs/html.md#renderer) + +### HTML ignore non-closed tags + +`htmlIgnoreNonClosedTags` option is used to control whether or not to +render non-closed HTML tags + +```java +SpannableConfiguration.builder(context) + .htmlIgnoreNonClosedTags(boolean) + .build(); +``` + +If not provided explicitly, default value `true` will be used (non-closed tags **won't** be rendered). diff --git a/docs/docs/factory.md b/docs/docs/factory.md index 86934fbf..9c3129af 100644 --- a/docs/docs/factory.md +++ b/docs/docs/factory.md @@ -1 +1,14 @@ -# Factory \ No newline at end of file +# Factory + +:::tip +`SpannableFactory` can be used to ignore some kinds of text markup. If, for example, +you do not wish to apply _emphasis_ styling to your final result, just return `null` +from `emphasis` factory method: +```java +@Nullable +@Override +public Object emphasis() { + return null; +} +``` +::: \ No newline at end of file diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index 8319cc2d..1e42c485 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -3,4 +3,95 @@ :::tip Installation Please follow [installation](/docs/install.md) instructions to learn how to add `Markwon` to your project +::: + +## Quick one + +This is the most simple way to set markdown to a `TextView` or any of its siblings: + +```java +Markwon.setMarkdown(textView, "**Hello there!**"); +``` + +The most simple way to obtain markdown to be applied _somewhere_ else: + +```java +// parsed and styled markdown +final CharSequence markdown = Markwon.markdown(context, "**Hello there!**"); + +// use it +Toast.makeText(context, markdown, Toast.LENGTH_LONG).show(); +``` + +## Longer one + +When you need to customize markdown parsing/rendering you can use [SpannableConfiguration](/docs/configure.md): + +```java +final SpannableConfiguration configuration = SpannableConfiguration.builder(context) + .asyncDrawableLoader(AsyncDrawableLoader.create()) + .build(); + +Markwon.setMarkdown(textView, configuration, "Are **you** still there?"); + +final CharSequence markdown = Markwon.markdown(configuration, "Are **you** still there?"); +Toast.makeText(context, markdown, Toast.LENGTH_LONG).show(); +``` + +## No magic one + +In order to understand how previous examples work, let's break them down: + +* construct a `Parser` (see: ) and parse markdown +* construct a `SpannableConfiguration` (if it's not provided) +* *render* parsed markdown to Spannable (via `SpannableRenderer`) +* prepares TextView to display images, tables and links +* sets text + +This flow answers the most simple usage of displaying markdown: one shot parsing +& configuration of relatively small markdown chunks. If your markdown contains +a lot of text or you plan to display multiple UI widgets with markdown you might +consider *stepping in* and taking control of this flow. + +The candidate requirements to *step in*: +* parsing and processing of parsed markdown in a background thread +* reusing `Parser` and/or `SpannableConfiguration` between multiple calls +* ignore images or tables specific logic (you know that markdown won't contain them) + +So, if we expand `Markwon.setMarkdown(textView, markdown)` method we will see the following: + +```java +// create a Parser instance (can be done manually) +// internally creates default Parser instance & registers `strike-through` & `tables` extension +final Parser parser = Markwon.createParser(); + +// core class to display markdown, can be obtained via this method, +// which creates default instance (no images handling though), +// or via `builder` method, which lets you to configure this instance +final SpannableConfiguration configuration = SpannableConfiguration.create(context); + +final SpannableRenderer renderer = new SpannableRenderer(); + +final Node node = parser.parse(markdown); +final CharSequence text = renderer.render(configuration, node); + +// for links in markdown to be clickable +textView.setMovementMethod(LinkMovementMethod.getInstance()); + +// we need these due to the limited nature of Spannables to invalidate TextView +Markwon.unscheduleDrawables(textView); +Markwon.unscheduleTableRows(textView); + +textView.setText(text); + +Markwon.scheduleDrawables(textView); +Markwon.scheduleTableRows(textView); +``` + +:::tip Note +If you are having trouble with `LinkMovementMethod` you can use +`Markwon.setText(textView, markdown, movementMethod)` method to specify _no_ movement +method (aka `null`) or own implementation. As an alternative to the system `LinkMovementMethod` +you can use [Better-Link-Movement-Method](https://github.com/saket/Better-Link-Movement-Method). +Please note that `Markwon.setText` method expects _parsed_ markdown as the second argument. ::: \ No newline at end of file diff --git a/docs/docs/html.md b/docs/docs/html.md index eeedc048..decd073b 100644 --- a/docs/docs/html.md +++ b/docs/docs/html.md @@ -195,5 +195,5 @@ required. Excluding `markwon-html-parser-impl` won't remove *all* the content between HTML tags. It will if `commonmark` decides that a specific fragment is a `HtmlBlock`, but it won't if fragment is considered a `HtmlInline` as `HtmlInline` -does not contain contents (just a tag definition). +does not contain content (just a tag definition). ::: \ No newline at end of file diff --git a/docs/docs/image-loader.md b/docs/docs/image-loader.md index d14d0008..d58c51dd 100644 --- a/docs/docs/image-loader.md +++ b/docs/docs/image-loader.md @@ -1 +1,152 @@ -# Images \ No newline at end of file +# Images + +By default `Markwon` doesn't handle images. Although `AsyncDrawable.Loader` is +defined in main artifact, it does not provide implementation. + +The interface is pretty simple: + +```java +public interface Loader { + + void load(@NonNull String destination, @NonNull AsyncDrawable drawable); + + void cancel(@NonNull String destination); +} +``` + +## AsyncDrawableLoader + +`AsyncDrawableLoader` from `markwon-image-loader` artifact can be used. + +:::tip Install +[Learn how to add](/docs/install.md#image-loader) `markwon-image-loader` to your project +::: + +Default instance of `AsyncDrawableLoader` can be obtain like this: + +```java +AsyncDrawableLoader.create(); +``` + +## Configuration + +If you wish to configure `AsyncDrawableLoader` `#builder` factory method can be used: + +```java +AsyncDrawableLoader.builder() + .build(); +``` + +### OkHttp client + +```java +AsyncDrawableLoader.builder() + .client(OkHttpClient) + .build(); +``` + +If not provided explicitly, default `new OkHttpClient()` will be used + +### Resources + +`android.content.res.Resources` to be used when obtaining an image +from Android assets folder **and** to create Bitmaps. + +```java +AsyncDrawableLoader.builder() + .resources(Resources) + .build(); +``` + +If not provided explicitly, default `Resources.getSystem()` will be used. + +:::warning +`Resources.getSystem()` can have unexpected side-effects (plus loading from +assets won't work). As a rule of thumb +always provide `AsyncDrawableLoader` with your Application's `Resources`. +To quote Android documentation for `#getSystem` method: + +> Return a global shared Resources object that provides access to only + system resources (no application resources), and is not configured + for the current screen (can not use dimension units, does not + change based on orientation, etc). + +::: + +### Executor service + +`ExecutorService` to be used to download images in background thread + +```java +AsyncDrawableLoader.builder() + .executorService(ExecutorService) + .build(); +``` + +If not provided explicitly, default `okHttpClient.dispatcher().executorService()` will be used + +### Error drawable + +`errorDrawable` to be used when image loader encountered an error loading image + +```java +AsyncDrawableLoader.builder() + .errorDrawable(Drawable) + .build(); +``` + +if not provided explicitly, default `null` value will be used. + +### Media decoder + +`MediaDecoder` is a simple asbtraction that encapsulates handling +of a specific image type. + +```java +AsyncDrawableLoader.builder() + .mediaDecoders(MediaDecoder...) + .mediaDecoders(List) + .build(); +``` + +If not provided explicitly, default `MediaDecoder`s will be used (SVG, GIF, plain) with +provided `Resources` and `gif-autoplay=true` + +`markwon-image-loader` comes with 3 `MediaDecoder` implementations: +* `SvgMediaDecoder` (based on [androidsvg](https://github.com/BigBadaboom/androidsvg)) +* `GifMediaDecoder` (based on [android-gif-drawable](https://github.com/koral--/android-gif-drawable)) +* `ImageMediaDecoder` (handling all _plain_ images) + +:::tip +Always add a _generic_ `MediaDecoder` instance at the end of the list. +Order does matter. For example: +```java{5} +AsyncDrawableLoader.builder() + .mediaDecoders( + SvgMediaDecoder.create(Resources), + GifMediaDecoder.create(boolean), + ImageMediaDecoder.create(Resources) + ) +.build(); +``` +::: + +#### SvgMediaDecoder + +```java +SvgMediaDecoder.create(Resources) +``` + +#### GifMediaDecoder + +```java +GifMediaDecoder.create(boolean) +``` + +`boolean` argument stands for `autoPlayGif` + +#### ImageMediaDecoder + +```java +ImageMediaDecoder.create(Resources) +``` \ No newline at end of file diff --git a/docs/docs/install.md b/docs/docs/install.md index caa3684f..730a6511 100644 --- a/docs/docs/install.md +++ b/docs/docs/install.md @@ -7,7 +7,78 @@ next: /docs/getting-started.md -proguard when using image-loader +In order to start using `Markwon` add this to your dependencies block +in your projects `build.gradle`: + +```groovy +implementation "ru.noties:markwon:${markwonVersion}" +``` + +This is core artifact that is sufficient to start displaying markdown in your Android applications. + +`Markwon` comes with more artifacts that cover additional functionality, but they are +**not** required to be used, as most of them provide implementations for functionality +that is _interfaced_ in the core artifact + +```groovy +implementation "ru.noties:markwon-image-loader:${markwonVersion}" +implementation "ru.noties:markwon-syntax-highlight:${markwonVersion}" +implementation "ru.noties:markwon-view:${markwonVersion}" +``` + +These artifacts share the same _version_ as the core artifact + +### Image loader + +```groovy +implementation "ru.noties:markwon-image-loader:${markwonVersion}" +``` + +Provides implementation of `AsyncDrawable.Loader` and comes with support for: +* SVG +* GIF +* Other image formats + +Please refer to documentation for [image loader](/docs/image-loader.md) module + +### Syntax highlight + +```groovy +implementation "ru.noties:markwon-syntax-highlight:${markwonVersion}" +``` + +Provides implementation of `SyntaxHighlight` and allows various syntax highlighting +in your markdown based Android applications. Comes with 2 ready-to-be-used themes: `light` and `dark`. +Please refer to documentation for [syntax highlight](/docs/syntax-highlight.md) module + +### View + +```groovy +implementation "ru.noties:markwon-view:${markwonVersion}" +``` + +Provides 2 widgets to display markdown: `MarkwonView` and `MarkwonViewCompat` (subclasses +of `TextView` and `AppCompatTextView` respectively). +Please refer to documentation for [view](/docs/view.md) module + +## Proguard + +When using `markwon-image-loader` artifact and Proguard is enabled, add these rules +to your proguard configuration: + +```proguard +-dontwarn okhttp3.** +-dontwarn okio.** + +-keep class com.caverock.androidsvg.** { *; } +-dontwarn com.caverock.androidsvg.** +``` + +They come from dependencies that `markwon-image-loader` is using. + +:::tip Other artifacts +Other artifacts do not require special Proguard rules +::: ## Snapshot @@ -29,7 +100,7 @@ allprojects { and then in your module `build.gradle`: ```groovy -implementation 'ru.noties:markwon:1.1.1-SNAPSHOT' +implementation "ru.noties:markwon:${markwonSnapshotVersion}" ``` Please note that `markwon-image-loader`, `markwon-syntax-highlight` diff --git a/docs/docs/syntax-highlight.md b/docs/docs/syntax-highlight.md index 92fb3283..95406581 100644 --- a/docs/docs/syntax-highlight.md +++ b/docs/docs/syntax-highlight.md @@ -1 +1,65 @@ -# Syntax highlight \ No newline at end of file +# 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. + +theme-default + + +theme-darkula + +--- + +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 + ); +} +``` + +> You can extend `Prism4jThemeBase` which has some helper methods \ No newline at end of file diff --git a/docs/docs/theme.md b/docs/docs/theme.md index e48261d4..c3e9e77b 100644 --- a/docs/docs/theme.md +++ b/docs/docs/theme.md @@ -4,6 +4,8 @@ Here is the list of properties that can be configured via `SpannableTheme#builde method. If you wish to control what is out of this list, you can use [SpannableFactory](/docs/factory.md) abstraction which lets you to gather full control of Spans that are used to display markdown. +* factory methods + ## Link color Controls the color of a [link](#) @@ -47,4 +49,74 @@ Controls the color of a list item. For ordered list: leading number, for unordered list: bullet. * UL -1. OL \ No newline at end of file +1. OL + + + +### Bullet item stroke width + +Border width of a bullet list item (level 2) + +* First +* * Second +* * * Third + + + +### Bullet width + +The width of the bullet item + +* First + * Second + * Third + + + +## Code + +### Inline code text color + +The color of the `code` content + + + +### Inline code background color + +The color of `background` of a code content + + + +### Block code text color + +``` +The color of code block text +``` + + + +### Block code background color + +``` +The color of background of code block text +``` + + + +### Block code leading margin + +Leading margin for the block code content + + + +### Code typeface + +Typeface of code content + + + +### Code text size + +Text size of code content + + diff --git a/docs/package-lock.json b/docs/package-lock.json index 8d4cf14d..5cc23227 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5700,6 +5700,11 @@ "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.3.tgz", "integrity": "sha512-x/OdaRzLYxAjmB+jIVlXuE3nX7tZTLDQxm58RkgjTLyQ+I290jYQvPS9cJjVN6SM3U6K6CHKYNgUtPNZmLblYQ==" }, + "markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" + }, "math-expression-evaluator": { "version": "1.2.17", "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", diff --git a/docs/package.json b/docs/package.json index 5e43df3e..d469413c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,6 +3,7 @@ "docs:build": "vuepress build" }, "dependencies": { + "markdown-it-task-lists": "^2.1.1", "vuepress": "^0.14.2" } } diff --git a/markwon-syntax-highlight/README.md b/markwon-syntax-highlight/README.md index 38d65358..4c7a0c74 100644 --- a/markwon-syntax-highlight/README.md +++ b/markwon-syntax-highlight/README.md @@ -2,9 +2,9 @@ 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. -![theme-default](./art/markwon-syntax-default.png) +![theme-default](../art/markwon-syntax-default.png) -![theme-darkula](./art/markwon-syntax-darkula.png) +![theme-darkula](../art/markwon-syntax-darkula.png) ---