From ab332e1410ef1e447479a81994178e0ded86f5be Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Sat, 27 May 2017 16:27:48 +0300 Subject: [PATCH] Updating README for `library` module --- library/README.md | 205 ++++++++++-------- .../renderer/SpannableMarkdownVisitor.java | 8 +- 2 files changed, 124 insertions(+), 89 deletions(-) diff --git a/library/README.md b/library/README.md index ae394b0e..8c5e1616 100644 --- a/library/README.md +++ b/library/README.md @@ -15,6 +15,9 @@ The aim for this library is to render markdown as first class citizen on Android The most basic example would be: ```java Markwon.setMarkdown(textView, "**Hello *there*!!**") + +// or +Markwon.setMarkdown(textView, spannableConfiguration, "**There hello~~!~~**") ``` Please note, that this library depends on [commonmark-java][commonmark-java] (and some extensions): @@ -47,6 +50,92 @@ public Builder htmlParser(SpannableHtmlParser htmlParser); public SpannableConfiguration build(); ``` +## Images + +By default this library does not render any of the images. It's done to simplify rendering of text-based markdown. But if images must be supported, then the `AsyncDrawable.Loader` can be specified whilst building a `SpannableConfiguration` instance: + +```java +final AsyncDrawable.Loader loader = new AsyncDrawable.Loader() { + @Override + public void load(@NonNull String destination, @NonNull final AsyncDrawable drawable) { + // `download` method is here for demonstration purposes, it's not included in this interface + download(destination, new Callback() { + @Override + public void onDownloaded(Drawable d) { + // additionally we can call `drawable.isAttached()` + // to ensure if AsyncDrawable is in layout + drawable.setResult(d); + } + }); + } + + @Override + public void cancel(@NonNull String destination) { + // cancel download here + } +}; + +// `this` here referrs to a Context instance +final SpannableConfiguration configuration = SpannableConfiguration.builder(this) + .asyncDrawableLoader(loader) + .build(); +``` + +There is also standalone artifact that supports image loading *out-of-box* (including support for **SVG** & **GIF**), but provides little to none configuration and could be somewhat not optimal. Please refer to the [README][mil-README] of the module. + + +## Tables + +Tables are supported but with some limitations. First of all: table will always take the full width of the TextView Canvas. Second: each column will have the same width (we do not calculate the weight of column) - so, a column width will be: `totalWidth / columnsNumber`. + + +## Syntax highlight +This library does not provide ready-to-be-used implementation of syntax highlight, but it can be added via `SyntaxHighlight` interface whilst building `SpannableConfiguration`: + +```java +final SyntaxHighlight syntaxHighlight = new SyntaxHighlight() { + @NonNull + @Override + public CharSequence highlight(@Nullable String info, @NonNull String code) { + // create Spanned of highlight here + return null; // must not return `null` here + } +}; + +final SpannableConfiguration configuration = SpannableConfiguration.builder(this) + .syntaxHighlight(syntaxHighlight) + .build(); +``` + +## Url processing +If you wish to process urls (links & images) that markdown contains, the `UrlProcessor` can be used: +```java +final UrlProcessor urlProcessor = new UrlProcessor() { + @NonNull + @Override + public String process(@NonNull String destination) { + // modify the `destination` or return as-is + return null; + } +}; + +final SpannableConfiguration configuration = SpannableConfiguration.builder(this) + .urlProcessor(urlProcessor) + .build(); +``` +The primary goal of additing this abstraction is to give ability to convert relative urls to absolute ones. If it fits your purpose, then `UrlProcessorRelativeToAbsolute` can be used: +```java +final UrlProcessor urlProcessor = new UrlProcessorRelativeToAbsolute("https://this-is-base.org"); +``` + +## Link resolver +Link resolver is used to navigate to clicked link. By default `LinkResolverDef` is used and it just constructs an `Intent` and launches activity that can handle it, or silently fails if activity cannot be resolved. The main interface: +```java +public interface Resolver { + void resolve(View view, @NonNull String link); +} +``` + ## Theme `SpannableTheme` controlls the appearance of rendered markdown. It has pretty reasonable defaults, which are established based on style of a TextView to which it is applied. It has some factory methods: ```java @@ -153,91 +242,6 @@ public Builder tableBorderWidth(@Dimension int tableBorderWidth); public Builder tableOddRowBackgroundColor(@ColorInt int tableOddRowBackgroundColor); ``` -## Images - -By default this library does not render any of the images. It's done to simplify rendering of text-based markdown. But if images must be supported, then the `AsyncDrawable.Loader` can be specified whilst building a `SpannableConfiguration` instance: - -```java -final AsyncDrawable.Loader loader = new AsyncDrawable.Loader() { - @Override - public void load(@NonNull String destination, @NonNull final AsyncDrawable drawable) { - // `download` method is here for demonstration purposes, it's not included in this interface - download(destination, new Callback() { - @Override - public void onDownloaded(Drawable d) { - // additionally we can call `drawable.isAttached()` - // to ensure if AsyncDrawable is in layout - drawable.setResult(d); - } - }); - } - - @Override - public void cancel(@NonNull String destination) { - // cancel download here - } -}; - -// `this` here referrs to a Context instance -final SpannableConfiguration configuration = SpannableConfiguration.builder(this) - .asyncDrawableLoader(loader) - .build(); -``` - -There is also standalone artifact that supports image loading *out-of-box* (including support for **SVG** & **GIF**), but provides little to none configuration and could be somewhat not optimal. Please refer to the [README][mil-README] of the module. - - -## Tables - -Tables are supported but with some limitations. First of all: table will always take the full width of the TextView Canvas. Second: each column will have the same width (we do not calculate the weight of column) - so, a column width will be: `totalWidth / columnsNumber`. - - -## Syntax highlight -This library does not provide ready-to-be-used implementation of syntax highlight, but it can be added via `SyntaxHighlight` interface whilst building `SpannableConfiguration`: - -```java -final SyntaxHighlight syntaxHighlight = new SyntaxHighlight() { - @NonNull - @Override - public CharSequence highlight(@Nullable String info, @NonNull String code) { - // create Spanned of highlight here - return null; // must not return `null` here - } -}; - -final SpannableConfiguration configuration = SpannableConfiguration.builder(this) - .syntaxHighlight(syntaxHighlight) - .build(); -``` - -## Url processing -If you wish to process urls (links & images) that markdown contains, the `UrlProcessor` can be used: -```java -final UrlProcessor urlProcessor = new UrlProcessor() { - @NonNull - @Override - public String process(@NonNull String destination) { - // modify the `destination` or return as-is - return null; - } -}; - -final SpannableConfiguration configuration = SpannableConfiguration.builder(this) - .urlProcessor(urlProcessor) - .build(); -``` -The primary goal of additing this abstraction is to give ability to convert relative urls to absolute ones. If it fits your purpose, then `UrlProcessorRelativeToAbsolute` can be used: -```java -final UrlProcessor urlProcessor = new UrlProcessorRelativeToAbsolute("https://this-is-base.org"); -``` - -## Link resolver -Link resolver is used to navigate to clicked link. By default `LinkResolverDef` is used and it just constructs an `Intent` and launches activity that can handle it, or silently fails if activity cannot be resolved. The main interface: -```java -public interface Resolver { - void resolve(View view, @NonNull String link); -} -``` ## HTML parser As markdown supports HTML to be inlined, we need to introduce another entity that does (limited) parsing. Obtain an instance of `SpannableHtmlParser` via one of these factory methods: @@ -247,5 +251,36 @@ SpannableHtmlParser.create(SpannableTheme, AsyncDrawable.Loader) SpannableHtmlParser.create(SpannableTheme, AsyncDrawable.Loader, UrlProcessor, LinkSpan.Resolver) ``` +Or, if further tweaking is requered builder methods: +```java +// creates empty builder +SpannableHtmlParser.builder(); + +// creates builder that is set-up to default values +SpannableHtmlParser.builderWithDefaults( + @NonNull SpannableTheme theme, + @Nullable AsyncDrawable.Loader asyncDrawableLoader, + @Nullable UrlProcessor urlProcessor, + @Nullable LinkSpan.Resolver resolver +) +``` + +Builder with defaults additionally handles these HTML tags: +* `b`, `strong` +* `i`, `em`, `cite`, `dfn` +* `sup` +* `sub` +* `u` +* `del`, `s`, `strike` +* `a` +* `img` (only if `AsyncDrawable.Loader` was provided) + +You can add own simple tags handling (or override default) via: +```java +SpannableHtmlParser.Builder.simpleTag(String, SpanProvider) +``` + +Please note, that not all tags are possible to handle via this. These are so called `void` tags ([link](https://www.w3.org/TR/html51/syntax.html#void-elements)) and so-called `html-blocks` ([link](http://spec.commonmark.org/0.18/#html-blocks)). An exception is made only for `img` tag -> it's possible to handle it via `imageProvider` property in `Builder` + [commonmark-java]: https://github.com/atlassian/commonmark-java [mil-README]: https://github.com/noties/Markwon/blob/master/library-image-loader/README.md diff --git a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java index 757f735f..022d706b 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java +++ b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java @@ -63,6 +63,10 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { private int blockQuoteIndent; private int listLevel; + private List pendingTableRow; + private boolean tableRowIsHeader; + private int tableRows; + public SpannableMarkdownVisitor( @NonNull SpannableConfiguration configuration, @NonNull SpannableStringBuilder builder @@ -265,10 +269,6 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { newLine(); } - private List pendingTableRow; - private boolean tableRowIsHeader; - private int tableRows; - @Override public void visit(CustomNode customNode) {