From 27ed17aaffc949f9a88574adb53d59c20db87a6c Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Mon, 26 Nov 2018 15:16:11 +0300 Subject: [PATCH] Move all html entities to markwon-html module --- .../ru/noties/markwon/MarkdownRenderer.java | 4 - markwon-html-parser-api/build.gradle | 23 - markwon-html-parser-api/gradle.properties | 3 - .../src/main/AndroidManifest.xml | 1 - .../build.gradle | 3 +- .../gradle.properties | 0 .../src/main/AndroidManifest.xml | 0 .../markwon/html/impl/AppendableUtils.java | 0 .../html/impl}/CssInlineStyleParser.java | 2 +- .../markwon/html/impl}/CssProperty.java | 2 +- .../html/impl/HtmlEmptyTagReplacement.java | 2 +- .../noties/markwon/html/impl/HtmlTagImpl.java | 2 +- .../html/impl/MarkwonHtmlParserImpl.java | 8 +- .../html/impl/MarkwonHtmlRendererImpl.java | 167 ++++++++ .../markwon/html/impl/TrimmingAppender.java | 0 .../html/impl/jsoup/UncheckedIOException.java | 0 .../html/impl/jsoup/helper/Normalizer.java | 0 .../html/impl/jsoup/helper/Validate.java | 0 .../html/impl/jsoup/nodes/Attribute.java | 0 .../html/impl/jsoup/nodes/Attributes.java | 0 .../impl/jsoup/nodes/CommonMarkEntities.java | 0 .../html/impl/jsoup/nodes/DocumentType.java | 0 .../impl/jsoup/parser/CharacterReader.java | 0 .../html/impl/jsoup/parser/ParseError.java | 0 .../impl/jsoup/parser/ParseErrorList.java | 0 .../markwon/html/impl/jsoup/parser/Token.java | 0 .../html/impl/jsoup/parser/Tokeniser.java | 0 .../impl/jsoup/parser/TokeniserState.java | 0 .../markwon/html/impl/span/SubScriptSpan.java | 25 ++ .../html/impl/span/SuperScriptSpan.java | 25 ++ .../html/impl}/tag/BlockquoteHandler.java | 7 +- .../html/impl}/tag/EmphasisHandler.java | 4 +- .../html/impl}/tag/HeadingHandler.java | 4 +- .../markwon/html/impl}/tag/ImageHandler.java | 6 +- .../html/impl}/tag/ImageSizeParserImpl.java | 6 +- .../markwon/html/impl}/tag/LinkHandler.java | 4 +- .../markwon/html/impl}/tag/ListHandler.java | 5 +- .../html/impl}/tag/SimpleTagHandler.java | 7 +- .../markwon/html/impl}/tag/StrikeHandler.java | 5 +- .../html/impl}/tag/StrongEmphasisHandler.java | 4 +- .../html/impl}/tag/SubScriptHandler.java | 7 +- .../html/impl}/tag/SuperScriptHandler.java | 7 +- .../html/impl}/tag/UnderlineHandler.java | 10 +- .../html/impl/CssInlineStyleParserTest.java | 239 +++++++++++ .../impl/HtmlEmptyTagReplacementTest.java | 0 .../html/impl/MarkwonHtmlParserImplTest.java | 0 .../html/impl/TrimmingAppenderTest.java | 0 .../jsoup/nodes/CommonMarkEntitiesTest.java | 0 .../impl/tag/ImageSizeParserImplTest.java | 186 ++++++++ markwon-image-loader/build.gradle | 37 -- markwon-image-loader/gradle.properties | 3 - .../src/main/AndroidManifest.xml | 1 - .../markwon/il/AsyncDrawableLoader.java | 405 ------------------ .../java/ru/noties/markwon/il/DataUri.java | 60 --- .../ru/noties/markwon/il/DataUriDecoder.java | 41 -- .../ru/noties/markwon/il/DataUriParser.java | 79 ---- .../markwon/il/DataUriSchemeHandler.java | 74 ---- .../ru/noties/markwon/il/DrawableUtils.java | 13 - .../noties/markwon/il/FileSchemeHandler.java | 109 ----- .../ru/noties/markwon/il/GifMediaDecoder.java | 91 ---- .../java/ru/noties/markwon/il/ImageItem.java | 39 -- .../noties/markwon/il/ImageMediaDecoder.java | 60 --- .../ru/noties/markwon/il/MediaDecoder.java | 20 - .../markwon/il/NetworkSchemeHandler.java | 89 ---- .../ru/noties/markwon/il/SchemeHandler.java | 25 -- .../ru/noties/markwon/il/SvgMediaDecoder.java | 81 ---- .../noties/markwon/il/DataUriParserTest.java | 119 ----- .../markwon/il/DataUriSchemeHandlerTest.java | 112 ----- .../markwon/syntax/Prism4jThemeDarkula.java | 4 + markwon/build.gradle | 3 - .../noties/markwon/MarkwonConfiguration.java | 39 +- .../ru/noties/markwon/SpannableFactory.java | 12 - .../noties/markwon/SpannableFactoryDef.java | 17 - .../java/ru/noties/markwon/html}/HtmlTag.java | 2 +- .../markwon/html}/MarkwonHtmlParser.java | 6 +- .../markwon/html}/MarkwonHtmlParserNoOp.java | 2 +- .../markwon/html/MarkwonHtmlRenderer.java | 30 ++ .../markwon/html/MarkwonHtmlRendererNoOp.java | 21 + .../html2/tag => html}/TagHandler.java | 3 +- .../renderer/html2/MarkwonHtmlRenderer.java | 101 ----- .../html2/MarkwonHtmlRendererImpl.java | 88 ---- .../renderer/MarkwonConfigurationTest.java | 2 +- settings.gradle | 2 +- 83 files changed, 761 insertions(+), 1797 deletions(-) delete mode 100644 markwon-html-parser-api/build.gradle delete mode 100644 markwon-html-parser-api/gradle.properties delete mode 100644 markwon-html-parser-api/src/main/AndroidManifest.xml rename {markwon-html-parser-impl => markwon-html}/build.gradle (88%) rename {markwon-html-parser-impl => markwon-html}/gradle.properties (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/AndroidManifest.xml (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/AppendableUtils.java (100%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/CssInlineStyleParser.java (99%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/CssProperty.java (94%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java (97%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java (99%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java (98%) create mode 100644 markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlRendererImpl.java rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/TrimmingAppender.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/UncheckedIOException.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Normalizer.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Validate.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attribute.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attributes.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntities.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/DocumentType.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/CharacterReader.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseError.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseErrorList.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Token.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Tokeniser.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/TokeniserState.java (100%) create mode 100644 markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SubScriptSpan.java create mode 100644 markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SuperScriptSpan.java rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/BlockquoteHandler.java (84%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/EmphasisHandler.java (80%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/HeadingHandler.java (85%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/ImageHandler.java (92%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/ImageSizeParserImpl.java (94%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/LinkHandler.java (89%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/ListHandler.java (93%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/SimpleTagHandler.java (84%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/StrikeHandler.java (84%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/StrongEmphasisHandler.java (81%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/SubScriptHandler.java (65%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/SuperScriptHandler.java (65%) rename {markwon/src/main/java/ru/noties/markwon/renderer/html2 => markwon-html/src/main/java/ru/noties/markwon/html/impl}/tag/UnderlineHandler.java (78%) create mode 100644 markwon-html/src/test/java/ru/noties/markwon/html/impl/CssInlineStyleParserTest.java rename {markwon-html-parser-impl => markwon-html}/src/test/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacementTest.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/test/java/ru/noties/markwon/html/impl/TrimmingAppenderTest.java (100%) rename {markwon-html-parser-impl => markwon-html}/src/test/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntitiesTest.java (100%) create mode 100644 markwon-html/src/test/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImplTest.java delete mode 100644 markwon-image-loader/build.gradle delete mode 100644 markwon-image-loader/gradle.properties delete mode 100644 markwon-image-loader/src/main/AndroidManifest.xml delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUri.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriParser.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriSchemeHandler.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DrawableUtils.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/FileSchemeHandler.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/GifMediaDecoder.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageItem.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageMediaDecoder.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/MediaDecoder.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/NetworkSchemeHandler.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/SchemeHandler.java delete mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/SvgMediaDecoder.java delete mode 100644 markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriParserTest.java delete mode 100644 markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriSchemeHandlerTest.java rename {markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api => markwon/src/main/java/ru/noties/markwon/html}/HtmlTag.java (98%) rename {markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api => markwon/src/main/java/ru/noties/markwon/html}/MarkwonHtmlParser.java (92%) rename {markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api => markwon/src/main/java/ru/noties/markwon/html}/MarkwonHtmlParserNoOp.java (95%) create mode 100644 markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRenderer.java create mode 100644 markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRendererNoOp.java rename markwon/src/main/java/ru/noties/markwon/{renderer/html2/tag => html}/TagHandler.java (91%) delete mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java delete mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java diff --git a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java index 053fde93..fc6af948 100644 --- a/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java +++ b/app/src/main/java/ru/noties/markwon/MarkdownRenderer.java @@ -77,10 +77,6 @@ public class MarkdownRenderer { ? prism4jThemeDefault : prism4JThemeDarkula; -// final int background = isLightTheme -// ? prism4jTheme.background() -// : 0x0Fffffff; - final Markwon2 markwon2 = Markwon2.builder(context) .use(CorePlugin.create()) .use(ImagesPlugin.createWithAssets(context)) diff --git a/markwon-html-parser-api/build.gradle b/markwon-html-parser-api/build.gradle deleted file mode 100644 index 8e38acbb..00000000 --- a/markwon-html-parser-api/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -apply plugin: 'com.android.library' - -android { - - compileSdkVersion config['compile-sdk'] - buildToolsVersion config['build-tools'] - - defaultConfig { - minSdkVersion config['min-sdk'] - targetSdkVersion config['target-sdk'] - versionCode 1 - versionName version - } -} - -dependencies { - - deps.with { - api it['support-annotations'] - } -} - -registerArtifact(this) diff --git a/markwon-html-parser-api/gradle.properties b/markwon-html-parser-api/gradle.properties deleted file mode 100644 index 5be4658d..00000000 --- a/markwon-html-parser-api/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -POM_NAME=Markwon -POM_ARTIFACT_ID=markwon-html-parser-api -POM_PACKAGING=aar \ No newline at end of file diff --git a/markwon-html-parser-api/src/main/AndroidManifest.xml b/markwon-html-parser-api/src/main/AndroidManifest.xml deleted file mode 100644 index 872543b3..00000000 --- a/markwon-html-parser-api/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/markwon-html-parser-impl/build.gradle b/markwon-html/build.gradle similarity index 88% rename from markwon-html-parser-impl/build.gradle rename to markwon-html/build.gradle index 2af46373..b61b12de 100644 --- a/markwon-html-parser-impl/build.gradle +++ b/markwon-html/build.gradle @@ -15,7 +15,7 @@ android { dependencies { - api project(':markwon-html-parser-api') + api project(':markwon') deps.with { api it['support-annotations'] @@ -25,6 +25,7 @@ dependencies { deps.test.with { testImplementation it['junit'] testImplementation it['robolectric'] + testImplementation it['ix-java'] } } diff --git a/markwon-html-parser-impl/gradle.properties b/markwon-html/gradle.properties similarity index 100% rename from markwon-html-parser-impl/gradle.properties rename to markwon-html/gradle.properties diff --git a/markwon-html-parser-impl/src/main/AndroidManifest.xml b/markwon-html/src/main/AndroidManifest.xml similarity index 100% rename from markwon-html-parser-impl/src/main/AndroidManifest.xml rename to markwon-html/src/main/AndroidManifest.xml diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/AppendableUtils.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/AppendableUtils.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/AppendableUtils.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/AppendableUtils.java diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/CssInlineStyleParser.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/CssInlineStyleParser.java similarity index 99% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/CssInlineStyleParser.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/CssInlineStyleParser.java index 9670d018..a42fab05 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/CssInlineStyleParser.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/CssInlineStyleParser.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.renderer.html2; +package ru.noties.markwon.html.impl; import android.support.annotation.NonNull; import android.support.annotation.Nullable; diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/CssProperty.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/CssProperty.java similarity index 94% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/CssProperty.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/CssProperty.java index aa490361..405d7c61 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/CssProperty.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/CssProperty.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.renderer.html2; +package ru.noties.markwon.html.impl; import android.support.annotation.NonNull; diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java similarity index 97% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java index c0d304dc..6604242b 100644 --- a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacement.java @@ -3,7 +3,7 @@ package ru.noties.markwon.html.impl; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; /** * This class will be used to append some text to output in order to diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java similarity index 99% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java index 01466106..8cedc767 100644 --- a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java @@ -7,7 +7,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; abstract class HtmlTagImpl implements HtmlTag { diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java similarity index 98% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java index 86f985a2..1bd639c6 100644 --- a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java @@ -14,10 +14,10 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import ru.noties.markwon.html.api.HtmlTag; -import ru.noties.markwon.html.api.HtmlTag.Block; -import ru.noties.markwon.html.api.HtmlTag.Inline; -import ru.noties.markwon.html.api.MarkwonHtmlParser; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.HtmlTag.Block; +import ru.noties.markwon.html.HtmlTag.Inline; +import ru.noties.markwon.html.MarkwonHtmlParser; import ru.noties.markwon.html.impl.jsoup.nodes.Attribute; import ru.noties.markwon.html.impl.jsoup.nodes.Attributes; import ru.noties.markwon.html.impl.jsoup.parser.CharacterReader; diff --git a/markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlRendererImpl.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlRendererImpl.java new file mode 100644 index 00000000..6ec8f26b --- /dev/null +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlRendererImpl.java @@ -0,0 +1,167 @@ +package ru.noties.markwon.html.impl; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import ru.noties.markwon.MarkwonConfiguration; +import ru.noties.markwon.SpannableBuilder; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.MarkwonHtmlParser; +import ru.noties.markwon.html.MarkwonHtmlRenderer; +import ru.noties.markwon.html.TagHandler; +import ru.noties.markwon.html.impl.tag.BlockquoteHandler; +import ru.noties.markwon.html.impl.tag.EmphasisHandler; +import ru.noties.markwon.html.impl.tag.HeadingHandler; +import ru.noties.markwon.html.impl.tag.ImageHandler; +import ru.noties.markwon.html.impl.tag.LinkHandler; +import ru.noties.markwon.html.impl.tag.ListHandler; +import ru.noties.markwon.html.impl.tag.StrikeHandler; +import ru.noties.markwon.html.impl.tag.StrongEmphasisHandler; +import ru.noties.markwon.html.impl.tag.SubScriptHandler; +import ru.noties.markwon.html.impl.tag.SuperScriptHandler; +import ru.noties.markwon.html.impl.tag.UnderlineHandler; + +public class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer { + + @NonNull + public static MarkwonHtmlRendererImpl create() { + return builderWithDefaults().build(); + } + + @NonNull + public static Builder builderWithDefaults() { + + final EmphasisHandler emphasisHandler = new EmphasisHandler(); + final StrongEmphasisHandler strongEmphasisHandler = new StrongEmphasisHandler(); + final StrikeHandler strikeHandler = new StrikeHandler(); + final UnderlineHandler underlineHandler = new UnderlineHandler(); + final ListHandler listHandler = new ListHandler(); + + return builder() + .handler("i", emphasisHandler) + .handler("em", emphasisHandler) + .handler("cite", emphasisHandler) + .handler("dfn", emphasisHandler) + .handler("b", strongEmphasisHandler) + .handler("strong", strongEmphasisHandler) + .handler("sup", new SuperScriptHandler()) + .handler("sub", new SubScriptHandler()) + .handler("u", underlineHandler) + .handler("ins", underlineHandler) + .handler("del", strikeHandler) + .handler("s", strikeHandler) + .handler("strike", strikeHandler) + .handler("a", new LinkHandler()) + .handler("ul", listHandler) + .handler("ol", listHandler) + .handler("img", ImageHandler.create()) + .handler("blockquote", new BlockquoteHandler()) + .handler("h1", new HeadingHandler(1)) + .handler("h2", new HeadingHandler(2)) + .handler("h3", new HeadingHandler(3)) + .handler("h4", new HeadingHandler(4)) + .handler("h5", new HeadingHandler(5)) + .handler("h6", new HeadingHandler(6)); + } + + @NonNull + public static Builder builder() { + return new Builder(); + } + + public static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F; + + private final Map tagHandlers; + + private MarkwonHtmlRendererImpl(@NonNull Map tagHandlers) { + this.tagHandlers = tagHandlers; + } + + @Override + public void render( + @NonNull final MarkwonConfiguration configuration, + @NonNull final SpannableBuilder builder, + @NonNull MarkwonHtmlParser parser) { + + final int end; + if (!configuration.htmlAllowNonClosedTags()) { + end = HtmlTag.NO_END; + } else { + end = builder.length(); + } + + parser.flushInlineTags(end, new MarkwonHtmlParser.FlushAction() { + @Override + public void apply(@NonNull List tags) { + + TagHandler handler; + + for (HtmlTag.Inline inline : tags) { + + // if tag is not closed -> do not render + if (!inline.isClosed()) { + continue; + } + + handler = tagHandler(inline.name()); + if (handler != null) { + handler.handle(configuration, builder, inline); + } + } + } + }); + + parser.flushBlockTags(end, new MarkwonHtmlParser.FlushAction() { + @Override + public void apply(@NonNull List tags) { + + TagHandler handler; + + for (HtmlTag.Block block : tags) { + + if (!block.isClosed()) { + continue; + } + + handler = tagHandler(block.name()); + if (handler != null) { + handler.handle(configuration, builder, block); + } else { + // see if any of children can be handled + apply(block.children()); + } + } + } + }); + + parser.reset(); + } + + @Nullable + @Override + public TagHandler tagHandler(@NonNull String tagName) { + return tagHandlers.get(tagName); + } + + public static class Builder { + + private final Map tagHandlers = new HashMap<>(2); + + @NonNull + public Builder handler(@NonNull String tagName, @NonNull TagHandler tagHandler) { + tagHandlers.put(tagName.toLowerCase(Locale.US), tagHandler); + return this; + } + + @NonNull + public MarkwonHtmlRendererImpl build() { + return new MarkwonHtmlRendererImpl(Collections.unmodifiableMap(tagHandlers)); + } + } +} diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/TrimmingAppender.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/TrimmingAppender.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/TrimmingAppender.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/TrimmingAppender.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/UncheckedIOException.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/UncheckedIOException.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/UncheckedIOException.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/UncheckedIOException.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Normalizer.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Normalizer.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Normalizer.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Normalizer.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Validate.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Validate.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Validate.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/helper/Validate.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attribute.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attribute.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attribute.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attribute.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attributes.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attributes.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attributes.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/Attributes.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntities.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntities.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntities.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntities.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/DocumentType.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/DocumentType.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/DocumentType.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/nodes/DocumentType.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/CharacterReader.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/CharacterReader.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/CharacterReader.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/CharacterReader.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseError.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseError.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseError.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseError.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseErrorList.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseErrorList.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseErrorList.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/ParseErrorList.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Token.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Token.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Token.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Token.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Tokeniser.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Tokeniser.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Tokeniser.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/Tokeniser.java diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/TokeniserState.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/TokeniserState.java similarity index 100% rename from markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/TokeniserState.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/jsoup/parser/TokeniserState.java diff --git a/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SubScriptSpan.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SubScriptSpan.java new file mode 100644 index 00000000..8eca8fdc --- /dev/null +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SubScriptSpan.java @@ -0,0 +1,25 @@ +package ru.noties.markwon.html.impl.span; + +import android.support.annotation.NonNull; +import android.text.TextPaint; +import android.text.style.MetricAffectingSpan; + +import ru.noties.markwon.html.impl.MarkwonHtmlRendererImpl; + +public class SubScriptSpan extends MetricAffectingSpan { + + @Override + public void updateDrawState(TextPaint tp) { + apply(tp); + } + + @Override + public void updateMeasureState(@NonNull TextPaint tp) { + apply(tp); + } + + private void apply(TextPaint paint) { + paint.setTextSize(paint.getTextSize() * MarkwonHtmlRendererImpl.SCRIPT_DEF_TEXT_SIZE_RATIO); + paint.baselineShift -= (int) (paint.ascent() / 2); + } +} diff --git a/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SuperScriptSpan.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SuperScriptSpan.java new file mode 100644 index 00000000..d33a2bea --- /dev/null +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/span/SuperScriptSpan.java @@ -0,0 +1,25 @@ +package ru.noties.markwon.html.impl.span; + +import android.support.annotation.NonNull; +import android.text.TextPaint; +import android.text.style.MetricAffectingSpan; + +import ru.noties.markwon.html.impl.MarkwonHtmlRendererImpl; + +public class SuperScriptSpan extends MetricAffectingSpan { + + @Override + public void updateDrawState(TextPaint tp) { + apply(tp); + } + + @Override + public void updateMeasureState(@NonNull TextPaint tp) { + apply(tp); + } + + private void apply(TextPaint paint) { + paint.setTextSize(paint.getTextSize() * MarkwonHtmlRendererImpl.SCRIPT_DEF_TEXT_SIZE_RATIO); + paint.baselineShift += (int) (paint.ascent() / 2); + } +} diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/BlockquoteHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/BlockquoteHandler.java similarity index 84% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/BlockquoteHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/BlockquoteHandler.java index 9f90dc93..2687ea94 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/BlockquoteHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/BlockquoteHandler.java @@ -1,10 +1,11 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; -import ru.noties.markwon.SpannableBuilder; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.SpannableBuilder; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.TagHandler; public class BlockquoteHandler extends TagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/EmphasisHandler.java similarity index 80% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/EmphasisHandler.java index aa452ebf..0385266a 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/EmphasisHandler.java @@ -1,10 +1,10 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; public class EmphasisHandler extends SimpleTagHandler { @Nullable diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/HeadingHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/HeadingHandler.java similarity index 85% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/HeadingHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/HeadingHandler.java index 99626259..d675351e 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/HeadingHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/HeadingHandler.java @@ -1,10 +1,10 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; public class HeadingHandler extends SimpleTagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageHandler.java similarity index 92% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageHandler.java index fe41f9d1..adbf745e 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageHandler.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -7,9 +7,9 @@ import android.text.TextUtils; import java.util.Map; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.impl.CssInlineStyleParser; import ru.noties.markwon.renderer.ImageSize; -import ru.noties.markwon.renderer.html2.CssInlineStyleParser; public class ImageHandler extends SimpleTagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageSizeParserImpl.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImpl.java similarity index 94% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageSizeParserImpl.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImpl.java index 56ad13c0..04556327 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ImageSizeParserImpl.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImpl.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -7,9 +7,9 @@ import android.text.TextUtils; import java.util.Map; +import ru.noties.markwon.html.impl.CssInlineStyleParser; +import ru.noties.markwon.html.impl.CssProperty; import ru.noties.markwon.renderer.ImageSize; -import ru.noties.markwon.renderer.html2.CssInlineStyleParser; -import ru.noties.markwon.renderer.html2.CssProperty; class ImageSizeParserImpl implements ImageHandler.ImageSizeParser { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/LinkHandler.java similarity index 89% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/LinkHandler.java index 74ac3c00..1faba510 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/LinkHandler.java @@ -1,11 +1,11 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; public class LinkHandler extends SimpleTagHandler { @Nullable diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ListHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ListHandler.java similarity index 93% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ListHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ListHandler.java index 671e2297..80094b5c 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/ListHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/ListHandler.java @@ -1,10 +1,11 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import ru.noties.markwon.MarkwonConfiguration; import ru.noties.markwon.SpannableBuilder; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.TagHandler; public class ListHandler extends TagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SimpleTagHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SimpleTagHandler.java similarity index 84% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SimpleTagHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SimpleTagHandler.java index d6fd93dc..ad68ef30 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SimpleTagHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SimpleTagHandler.java @@ -1,11 +1,12 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import ru.noties.markwon.SpannableBuilder; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.SpannableBuilder; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.TagHandler; public abstract class SimpleTagHandler extends TagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrikeHandler.java similarity index 84% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrikeHandler.java index 9b8cad2d..4d59b152 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrikeHandler.java @@ -1,10 +1,11 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import ru.noties.markwon.MarkwonConfiguration; import ru.noties.markwon.SpannableBuilder; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.TagHandler; public class StrikeHandler extends TagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrongEmphasisHandler.java similarity index 81% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrongEmphasisHandler.java index 7e50bc72..6b5f8230 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/StrongEmphasisHandler.java @@ -1,10 +1,10 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; public class StrongEmphasisHandler extends SimpleTagHandler { @Nullable diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SubScriptHandler.java similarity index 65% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SubScriptHandler.java index 145cf261..9adf5684 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SubScriptHandler.java @@ -1,15 +1,16 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.impl.span.SubScriptSpan; public class SubScriptHandler extends SimpleTagHandler { @Nullable @Override public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull HtmlTag tag) { - return configuration.factory().subScript(configuration.theme()); + return new SubScriptSpan(); } } diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SuperScriptHandler.java similarity index 65% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SuperScriptHandler.java index 60da420d..42e00075 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/SuperScriptHandler.java @@ -1,15 +1,16 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.impl.span.SuperScriptSpan; public class SuperScriptHandler extends SimpleTagHandler { @Nullable @Override public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull HtmlTag tag) { - return configuration.factory().superScript(configuration.theme()); + return new SuperScriptSpan(); } } diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/UnderlineHandler.java similarity index 78% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java rename to markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/UnderlineHandler.java index d9e03e2a..fb492dda 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java +++ b/markwon-html/src/main/java/ru/noties/markwon/html/impl/tag/UnderlineHandler.java @@ -1,10 +1,12 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html.impl.tag; import android.support.annotation.NonNull; +import android.text.style.UnderlineSpan; -import ru.noties.markwon.SpannableBuilder; import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; +import ru.noties.markwon.SpannableBuilder; +import ru.noties.markwon.html.HtmlTag; +import ru.noties.markwon.html.TagHandler; public class UnderlineHandler extends TagHandler { @@ -23,7 +25,7 @@ public class UnderlineHandler extends TagHandler { SpannableBuilder.setSpans( builder, - configuration.factory().underline(), + new UnderlineSpan(), tag.start(), tag.end() ); diff --git a/markwon-html/src/test/java/ru/noties/markwon/html/impl/CssInlineStyleParserTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/CssInlineStyleParserTest.java new file mode 100644 index 00000000..36c7d798 --- /dev/null +++ b/markwon-html/src/test/java/ru/noties/markwon/html/impl/CssInlineStyleParserTest.java @@ -0,0 +1,239 @@ +package ru.noties.markwon.html.impl; + +import android.support.annotation.NonNull; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ix.Ix; +import ix.IxFunction; +import ru.noties.markwon.test.TestUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static ru.noties.markwon.test.TestUtils.with; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class CssInlineStyleParserTest { + + private CssInlineStyleParser.Impl impl; + + @Before + public void before() { + impl = new CssInlineStyleParser.Impl(); + } + + @Test + public void simple_single_pair() { + + final String input = "key: value;"; + + final List list = listProperties(input); + + assertEquals(1, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key", cssProperty.key()); + assertEquals("value", cssProperty.value()); + } + }); + } + + @Test + public void simple_two_pairs() { + + final String input = "key1: value1; key2: value2;"; + + final List list = listProperties(input); + + assertEquals(2, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key1", cssProperty.key()); + assertEquals("value1", cssProperty.value()); + } + }); + + with(list.get(1), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key2", cssProperty.key()); + assertEquals("value2", cssProperty.value()); + } + }); + } + + @Test + public void one_pair_eof() { + + final String input = "key: value"; + final List list = listProperties(input); + assertEquals(1, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key", cssProperty.key()); + assertEquals("value", cssProperty.value()); + } + }); + } + + @Test + public void one_pair_eof_whitespaces() { + + final String input = "key: value \n\n\t"; + final List list = listProperties(input); + assertEquals(1, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key", cssProperty.key()); + assertEquals("value", cssProperty.value()); + } + }); + } + + @Test + public void white_spaces() { + + final String input = "\n\n\n\t \t key1 \n\n\n\t : \n\n\n\n \t value1 \n\n\n\n ; \n key2\n : \n value2 \n ; "; + final List list = listProperties(input); + assertEquals(2, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key1", cssProperty.key()); + assertEquals("value1", cssProperty.value()); + } + }); + + with(list.get(1), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key2", cssProperty.key()); + assertEquals("value2", cssProperty.value()); + } + }); + } + + @Test + public void list_of_keys() { + + final String input = "key1 key2 key3 key4"; + final List list = listProperties(input); + + assertEquals(0, list.size()); + } + + @Test + public void list_of_keys_and_value() { + + final String input = "key1 key2 key3 key4: value4"; + final List list = listProperties(input); + assertEquals(1, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key4", cssProperty.key()); + assertEquals("value4", cssProperty.value()); + } + }); + } + + @Test + public void list_of_keys_separated_by_semi_colon() { + + final String input = "key1;key2;key3;key4;"; + final List list = listProperties(input); + assertEquals(0, list.size()); + } + + @Test + public void key_value_with_invalid_between() { + + final String input = "key1: value1; key2 key3: value3;"; + final List list = listProperties(input); + + assertEquals(2, list.size()); + + with(list.get(0), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key1", cssProperty.key()); + assertEquals("value1", cssProperty.value()); + } + }); + + with(list.get(1), new TestUtils.Action() { + @Override + public void apply(@NonNull CssProperty cssProperty) { + assertEquals("key3", cssProperty.key()); + assertEquals("value3", cssProperty.value()); + } + }); + } + + @Test + public void css_functions() { + + final Map map = new HashMap() {{ + put("attr", "\" (\" attr(href) \")\""); + put("calc", "calc(100% - 100px)"); + put("cubic-bezier", "cubic-bezier(0.1, 0.7, 1.0, 0.1)"); + put("hsl", "hsl(120,100%,50%)"); + put("hsla", "hsla(120,100%,50%,0.3)"); + put("linear-gradient", "linear-gradient(red, yellow, blue)"); + put("radial-gradient", "radial-gradient(red, green, blue)"); + put("repeating-linear-gradient", "repeating-linear-gradient(red, yellow 10%, green 20%)"); + put("repeating-radial-gradient", "repeating-radial-gradient(red, yellow 10%, green 15%)"); + put("rgb", "rgb(255,0,0)"); + put("rgba", "rgba(255,0,0,0.3)"); + put("var", "var(--some-variable)"); + put("url", "url(\"url.gif\")"); + }}; + + final StringBuilder builder = new StringBuilder(); + for (Map.Entry entry: map.entrySet()) { + builder.append(entry.getKey()) + .append(':') + .append(entry.getValue()) + .append(';'); + } + + for (CssProperty cssProperty: impl.parse(builder.toString())) { + final String value = map.remove(cssProperty.key()); + assertNotNull(cssProperty.key(), value); + assertEquals(cssProperty.key(), value, cssProperty.value()); + } + + assertEquals(0, map.size()); + } + + @NonNull + private List listProperties(@NonNull String input) { + return Ix.from(impl.parse(input)) + .map(new IxFunction() { + @Override + public CssProperty apply(CssProperty cssProperty) { + return cssProperty.mutate(); + } + }) + .toList(); + } +} \ No newline at end of file diff --git a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacementTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacementTest.java similarity index 100% rename from markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacementTest.java rename to markwon-html/src/test/java/ru/noties/markwon/html/impl/HtmlEmptyTagReplacementTest.java diff --git a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java similarity index 100% rename from markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java rename to markwon-html/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java diff --git a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/TrimmingAppenderTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/TrimmingAppenderTest.java similarity index 100% rename from markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/TrimmingAppenderTest.java rename to markwon-html/src/test/java/ru/noties/markwon/html/impl/TrimmingAppenderTest.java diff --git a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntitiesTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntitiesTest.java similarity index 100% rename from markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntitiesTest.java rename to markwon-html/src/test/java/ru/noties/markwon/html/impl/jsoup/nodes/CommonMarkEntitiesTest.java diff --git a/markwon-html/src/test/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImplTest.java b/markwon-html/src/test/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImplTest.java new file mode 100644 index 00000000..006427e8 --- /dev/null +++ b/markwon-html/src/test/java/ru/noties/markwon/html/impl/tag/ImageSizeParserImplTest.java @@ -0,0 +1,186 @@ +package ru.noties.markwon.html.impl.tag; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import ru.noties.markwon.renderer.ImageSize; +import ru.noties.markwon.renderer.html2.CssInlineStyleParser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class ImageSizeParserImplTest { + + private static final float DELTA = 1e-7F; + + private ImageSizeParserImpl impl; + + @Before + public void before() { + impl = new ImageSizeParserImpl(CssInlineStyleParser.create()); + } + + @Test + public void nothing() { + assertNull(impl.parse(Collections.emptyMap())); + } + + @Test + public void width_height_from_style() { + + final String style = "width: 123; height: 321"; + + assertImageSize( + new ImageSize(dimension(123, null), dimension(321, null)), + impl.parse(Collections.singletonMap("style", style)) + ); + } + + @Test + public void style_has_higher_priority_width() { + + // if property is found in styles, do not lookup raw attribute + final Map attributes = new HashMap() {{ + put("style", "width: 43"); + put("width", "991"); + }}; + + assertImageSize( + new ImageSize(dimension(43, null), null), + impl.parse(attributes) + ); + } + + @Test + public void style_has_higher_priority_height() { + + // if property is found in styles, do not lookup raw attribute + final Map attributes = new HashMap() {{ + put("style", "height: 177"); + put("height", "8"); + }}; + + assertImageSize( + new ImageSize(null, dimension(177, null)), + impl.parse(attributes) + ); + } + + @Test + public void width_style_height_attributes() { + + final Map attributes = new HashMap() {{ + put("style", "width: 99"); + put("height", "7"); + }}; + + assertImageSize( + new ImageSize(dimension(99, null), dimension(7, null)), + impl.parse(attributes) + ); + } + + @Test + public void height_style_width_attributes() { + + final Map attributes = new HashMap() {{ + put("style", "height: 15"); + put("width", "88"); + }}; + + assertImageSize( + new ImageSize(dimension(88, null), dimension(15, null)), + impl.parse(attributes) + ); + } + + @Test + public void non_empty_styles_width_height_attributes() { + + final Map attributes = new HashMap() {{ + put("style", "key1: value1; width0: 123; height0: 99"); + put("width", "40"); + put("height", "77"); + }}; + + assertImageSize( + new ImageSize(dimension(40, null), dimension(77, null)), + impl.parse(attributes) + ); + } + + @Test + public void dimension_units() { + + final Map map = new HashMap() {{ + put("100", dimension(100, null)); + put("100%", dimension(100, "%")); + put("1%", dimension(1, "%")); + put("0.2em", dimension(0.2F, "em")); + put("155px", dimension(155, "px")); + put("67blah", dimension(67, "blah")); + put("-1", dimension(-1, null)); + put("-0.01pt", dimension(-0.01F, "pt")); + }}; + + for (Map.Entry entry : map.entrySet()) { + assertDimension(entry.getKey(), entry.getValue(), impl.dimension(entry.getKey())); + } + } + + @Test + public void bad_dimension() { + + final String[] dimensions = { + "calc(5px + 10rem)", + "whataver6", + "165 165", + "!@#$%^&*(%" + }; + + for (String dimension : dimensions) { + assertNull(dimension, impl.dimension(dimension)); + } + } + + private static void assertImageSize(@Nullable ImageSize expected, @Nullable ImageSize actual) { + if (expected == null) { + assertNull(actual); + } else { + assertNotNull(actual); + assertDimension("width", expected.width, actual.width); + assertDimension("height", expected.height, actual.height); + } + } + + private static void assertDimension( + @NonNull String name, + @Nullable ImageSize.Dimension expected, + @Nullable ImageSize.Dimension actual) { + if (expected == null) { + assertNull(name, actual); + } else { + assertNotNull(name, actual); + assertEquals(name, expected.value, actual.value, DELTA); + assertEquals(name, expected.unit, actual.unit); + } + } + + @NonNull + private static ImageSize.Dimension dimension(float value, @Nullable String unit) { + return new ImageSize.Dimension(value, unit); + } +} \ No newline at end of file diff --git a/markwon-image-loader/build.gradle b/markwon-image-loader/build.gradle deleted file mode 100644 index fd4293c8..00000000 --- a/markwon-image-loader/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -apply plugin: 'com.android.library' - -android { - - compileSdkVersion config['compile-sdk'] - buildToolsVersion config['build-tools'] - - defaultConfig { - minSdkVersion config['min-sdk'] - targetSdkVersion config['target-sdk'] - versionCode 1 - versionName version - } - - lintOptions { - // okio.... - disable 'InvalidPackage' - } -} - -dependencies { - - api project(':markwon') - - deps.with { - api it['android-svg'] - api it['android-gif'] - api it['okhttp'] - } - - deps['test'].with { - testImplementation it['junit'] - testImplementation it['robolectric'] - } -} - -registerArtifact(this) diff --git a/markwon-image-loader/gradle.properties b/markwon-image-loader/gradle.properties deleted file mode 100644 index 4dbec709..00000000 --- a/markwon-image-loader/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -POM_NAME=Markwon-Image-Loader -POM_ARTIFACT_ID=markwon-image-loader -POM_PACKAGING=aar \ No newline at end of file diff --git a/markwon-image-loader/src/main/AndroidManifest.xml b/markwon-image-loader/src/main/AndroidManifest.xml deleted file mode 100644 index 35da8e8a..00000000 --- a/markwon-image-loader/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java deleted file mode 100644 index 5f7a5f01..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java +++ /dev/null @@ -1,405 +0,0 @@ -package ru.noties.markwon.il; - -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import okhttp3.OkHttpClient; -import ru.noties.markwon.image.AsyncDrawable; - -public class AsyncDrawableLoader implements AsyncDrawable.Loader { - - @NonNull - public static AsyncDrawableLoader create() { - return builder().build(); - } - - @NonNull - public static AsyncDrawableLoader.Builder builder() { - return new Builder(); - } - - private final ExecutorService executorService; - private final Handler mainThread; - private final Drawable errorDrawable; - private final Map schemeHandlers; - private final List mediaDecoders; - - private final Map> requests; - - AsyncDrawableLoader(Builder builder) { - this.executorService = builder.executorService; - this.mainThread = new Handler(Looper.getMainLooper()); - this.errorDrawable = builder.errorDrawable; - this.schemeHandlers = builder.schemeHandlers; - this.mediaDecoders = builder.mediaDecoders; - this.requests = new HashMap<>(3); - } - - - @Override - public void load(@NonNull String destination, @NonNull AsyncDrawable drawable) { - // if drawable is not a link -> show loading placeholder... - requests.put(destination, execute(destination, drawable)); - } - - @Override - public void cancel(@NonNull String destination) { - - final Future request = requests.remove(destination); - if (request != null) { - request.cancel(true); - } - - for (SchemeHandler schemeHandler : schemeHandlers.values()) { - schemeHandler.cancel(destination); - } - } - - private Future execute(@NonNull final String destination, @NonNull AsyncDrawable drawable) { - - final WeakReference reference = new WeakReference(drawable); - - // todo: should we cancel pending request for the same destination? - // we _could_ but there is possibility that one resource is request in multiple places - - // todo: error handing (simply applying errorDrawable is not a good solution - // as reason for an error is unclear (no scheme handler, no input data, error decoding, etc) - - // todo: more efficient ImageMediaDecoder... BitmapFactory.decodeStream is a bit not optimal - // for big images for sure. We _could_ introduce internal Drawable that will check for - // image bounds (but we will need to cache inputStream in order to inspect and optimize - // input image...) - - return executorService.submit(new Runnable() { - @Override - public void run() { - - final ImageItem item; - - final Uri uri = Uri.parse(destination); - - final SchemeHandler schemeHandler = schemeHandlers.get(uri.getScheme()); - if (schemeHandler != null) { - item = schemeHandler.handle(destination, uri); - } else { - item = null; - } - - final InputStream inputStream = item != null - ? item.inputStream() - : null; - - Drawable result = null; - - if (inputStream != null) { - try { - - final String fileName = item.fileName(); - final MediaDecoder mediaDecoder = fileName != null - ? mediaDecoderFromFile(fileName) - : mediaDecoderFromContentType(item.contentType()); - - if (mediaDecoder != null) { - result = mediaDecoder.decode(inputStream); - } - - } finally { - try { - inputStream.close(); - } catch (IOException e) { - // ignored - } - } - } - - // if result is null, we assume it's an error - if (result == null) { - result = errorDrawable; - } - - if (result != null) { - final Drawable out = result; - mainThread.post(new Runnable() { - @Override - public void run() { - final AsyncDrawable asyncDrawable = reference.get(); - if (asyncDrawable != null && asyncDrawable.isAttached()) { - asyncDrawable.setResult(out); - } - } - }); - } - - requests.remove(destination); - } - }); - } - - @Nullable - private MediaDecoder mediaDecoderFromFile(@NonNull String fileName) { - - MediaDecoder out = null; - - for (MediaDecoder mediaDecoder : mediaDecoders) { - if (mediaDecoder.canDecodeByFileName(fileName)) { - out = mediaDecoder; - break; - } - } - - return out; - } - - @Nullable - private MediaDecoder mediaDecoderFromContentType(@Nullable String contentType) { - - MediaDecoder out = null; - - for (MediaDecoder mediaDecoder : mediaDecoders) { - if (mediaDecoder.canDecodeByContentType(contentType)) { - out = mediaDecoder; - break; - } - } - - return out; - } - - // todo: as now we have different layers of abstraction (for scheme handling and media decoding) - // we no longer should add dependencies implicitly, it would be way better to allow adding - // multiple artifacts (file, data, network, svg, gif)... at least, maybe we can extract API - // for this module (without implementations), but keep _all-in_ (fat) artifact with all of these. - public static class Builder { - - /** - * @deprecated 2.0.0 add {@link NetworkSchemeHandler} directly - */ - @Deprecated - private OkHttpClient client; - - /** - * @deprecated 2.0.0 construct {@link MediaDecoder} and {@link SchemeHandler} appropriately - */ - @Deprecated - private Resources resources; - - private ExecutorService executorService; - private Drawable errorDrawable; - - // @since 1.1.0 - private final List mediaDecoders = new ArrayList<>(3); - - // @since 2.0.0 - private final Map schemeHandlers = new HashMap<>(3); - - /** - * @deprecated 2.0.0 add {@link NetworkSchemeHandler} directly - */ - @NonNull - @Deprecated - public Builder client(@NonNull OkHttpClient client) { - this.client = client; - return this; - } - - /** - * Supplied resources argument will be used to open files from assets directory - * and to create default {@link MediaDecoder}\'s which require resources instance - * - * @return self - */ - @NonNull - public Builder resources(@NonNull Resources resources) { - this.resources = resources; - return this; - } - - @NonNull - public Builder executorService(@NonNull ExecutorService executorService) { - this.executorService = executorService; - return this; - } - - @NonNull - public Builder errorDrawable(@NonNull Drawable errorDrawable) { - this.errorDrawable = errorDrawable; - return this; - } - - /** - * @since 2.0.0 - */ - @SuppressWarnings("UnusedReturnValue") - @NonNull - public Builder addSchemeHandler(@NonNull SchemeHandler schemeHandler) { - - SchemeHandler previous; - - for (String scheme : schemeHandler.schemes()) { - previous = schemeHandlers.put(scheme, schemeHandler); - if (previous != null) { - throw new IllegalStateException(String.format("Multiple scheme handlers handle " + - "the same scheme: `%s`, %s %s", scheme, previous, schemeHandler)); - } - } - - return this; - } - - /** - * @see #addMediaDecoder(MediaDecoder) - * @see #addMediaDecoders(MediaDecoder...) - * @see #addMediaDecoders(Iterable) - * @since 1.1.0 - * @deprecated 2.0.0 - */ - @Deprecated - @NonNull - public Builder mediaDecoders(@NonNull List mediaDecoders) { - - // previously it was clearing before adding - - for (MediaDecoder mediaDecoder : mediaDecoders) { - this.mediaDecoders.add(requireNonNull(mediaDecoder)); - } - - return this; - } - - /** - * @see #addMediaDecoder(MediaDecoder) - * @see #addMediaDecoders(MediaDecoder...) - * @see #addMediaDecoders(Iterable) - * @since 1.1.0 - * @deprecated 2.0.0 - */ - @NonNull - @Deprecated - public Builder mediaDecoders(MediaDecoder... mediaDecoders) { - - // previously it was clearing before adding - - final int length = mediaDecoders != null - ? mediaDecoders.length - : 0; - - if (length > 0) { - for (int i = 0; i < length; i++) { - this.mediaDecoders.add(requireNonNull(mediaDecoders[i])); - } - } - - return this; - } - - /** - * @see SvgMediaDecoder - * @see GifMediaDecoder - * @see ImageMediaDecoder - * @since 2.0.0 - */ - @NonNull - public Builder addMediaDecoder(@NonNull MediaDecoder mediaDecoder) { - mediaDecoders.add(mediaDecoder); - return this; - } - - /** - * @see SvgMediaDecoder - * @see GifMediaDecoder - * @see ImageMediaDecoder - * @since 2.0.0 - */ - @NonNull - public Builder addMediaDecoders(@NonNull Iterable mediaDecoders) { - for (MediaDecoder mediaDecoder : mediaDecoders) { - this.mediaDecoders.add(requireNonNull(mediaDecoder)); - } - return this; - } - - /** - * @see SvgMediaDecoder - * @see GifMediaDecoder - * @see ImageMediaDecoder - * @since 2.0.0 - */ - @NonNull - public Builder addMediaDecoders(MediaDecoder... mediaDecoders) { - - final int length = mediaDecoders != null - ? mediaDecoders.length - : 0; - - if (length > 0) { - for (int i = 0; i < length; i++) { - this.mediaDecoders.add(requireNonNull(mediaDecoders[i])); - } - } - - return this; - } - - @NonNull - public AsyncDrawableLoader build() { - - // I think we should deprecate this... - if (resources == null) { - resources = Resources.getSystem(); - } - - if (executorService == null) { - // @since 2.0.0 we are using newCachedThreadPool instead - // of `okHttpClient.dispatcher().executorService()` - executorService = Executors.newCachedThreadPool(); - } - - // @since 2.0.0 - // put default scheme handlers (to mimic previous behavior) - // remove in 3.0.0 with plugins - if (schemeHandlers.size() == 0) { - if (client == null) { - client = new OkHttpClient(); - } - addSchemeHandler(NetworkSchemeHandler.create(client)); - addSchemeHandler(FileSchemeHandler.createWithAssets(resources.getAssets())); - addSchemeHandler(DataUriSchemeHandler.create()); - } - - // add default media decoders if not specified - // remove in 3.0.0 with plugins - if (mediaDecoders.size() == 0) { - mediaDecoders.add(SvgMediaDecoder.create(resources)); - mediaDecoders.add(GifMediaDecoder.create(true)); - mediaDecoders.add(ImageMediaDecoder.create(resources)); - } - - return new AsyncDrawableLoader(this); - } - } - - // @since 2.0.0 - @NonNull - private static T requireNonNull(@Nullable T t) { - if (t == null) { - throw new NullPointerException(); - } - return t; - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUri.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUri.java deleted file mode 100644 index 697b7b2e..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUri.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.noties.markwon.il; - -import android.support.annotation.Nullable; - -public class DataUri { - - private final String contentType; - private final boolean base64; - private final String data; - - public DataUri(@Nullable String contentType, boolean base64, @Nullable String data) { - this.contentType = contentType; - this.base64 = base64; - this.data = data; - } - - @Nullable - public String contentType() { - return contentType; - } - - public boolean base64() { - return base64; - } - - @Nullable - public String data() { - return data; - } - - @Override - public String toString() { - return "DataUri{" + - "contentType='" + contentType + '\'' + - ", base64=" + base64 + - ", data='" + data + '\'' + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DataUri dataUri = (DataUri) o; - - if (base64 != dataUri.base64) return false; - if (contentType != null ? !contentType.equals(dataUri.contentType) : dataUri.contentType != null) - return false; - return data != null ? data.equals(dataUri.data) : dataUri.data == null; - } - - @Override - public int hashCode() { - int result = contentType != null ? contentType.hashCode() : 0; - result = 31 * result + (base64 ? 1 : 0); - result = 31 * result + (data != null ? data.hashCode() : 0); - return result; - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java deleted file mode 100644 index ffb0d840..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java +++ /dev/null @@ -1,41 +0,0 @@ -package ru.noties.markwon.il; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.util.Base64; - -public abstract class DataUriDecoder { - - @Nullable - public abstract byte[] decode(@NonNull DataUri dataUri); - - @NonNull - public static DataUriDecoder create() { - return new Impl(); - } - - static class Impl extends DataUriDecoder { - - @Nullable - @Override - public byte[] decode(@NonNull DataUri dataUri) { - - final String data = dataUri.data(); - - if (!TextUtils.isEmpty(data)) { - try { - if (dataUri.base64()) { - return Base64.decode(data.getBytes("UTF-8"), Base64.DEFAULT); - } else { - return data.getBytes("UTF-8"); - } - } catch (Throwable t) { - return null; - } - } else { - return null; - } - } - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriParser.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriParser.java deleted file mode 100644 index 63744a42..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriParser.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.noties.markwon.il; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -public abstract class DataUriParser { - - @Nullable - public abstract DataUri parse(@NonNull String input); - - - @NonNull - public static DataUriParser create() { - return new Impl(); - } - - static class Impl extends DataUriParser { - - @Nullable - @Override - public DataUri parse(@NonNull String input) { - - final int index = input.indexOf(','); - // we expect exactly one comma - if (index < 0) { - return null; - } - - final String contentType; - final boolean base64; - - if (index > 0) { - final String part = input.substring(0, index); - final String[] parts = part.split(";"); - final int length = parts.length; - if (length > 0) { - // if one: either content-type or base64 - if (length == 1) { - final String value = parts[0]; - if ("base64".equals(value)) { - contentType = null; - base64 = true; - } else { - contentType = value.indexOf('/') > -1 - ? value - : null; - base64 = false; - } - } else { - contentType = parts[0].indexOf('/') > -1 - ? parts[0] - : null; - base64 = "base64".equals(parts[length - 1]); - } - } else { - contentType = null; - base64 = false; - } - } else { - contentType = null; - base64 = false; - } - - final String data; - if (index < input.length()) { - final String value = input.substring(index + 1, input.length()).replaceAll("\n", ""); - if (value.length() == 0) { - data = null; - } else { - data = value; - } - } else { - data = null; - } - - return new DataUri(contentType, base64, data); - } - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriSchemeHandler.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriSchemeHandler.java deleted file mode 100644 index c70ea863..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriSchemeHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -package ru.noties.markwon.il; - -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.ByteArrayInputStream; -import java.util.Collection; -import java.util.Collections; - -/** - * @since 2.0.0 - */ -public class DataUriSchemeHandler extends SchemeHandler { - - @NonNull - public static DataUriSchemeHandler create() { - return new DataUriSchemeHandler(DataUriParser.create(), DataUriDecoder.create()); - } - - private static final String START = "data:"; - - private final DataUriParser uriParser; - private final DataUriDecoder uriDecoder; - - @SuppressWarnings("WeakerAccess") - DataUriSchemeHandler(@NonNull DataUriParser uriParser, @NonNull DataUriDecoder uriDecoder) { - this.uriParser = uriParser; - this.uriDecoder = uriDecoder; - } - - @Nullable - @Override - public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { - - if (!raw.startsWith(START)) { - return null; - } - - String part = raw.substring(START.length()); - - // this part is added to support `data://` with which this functionality was released - if (part.startsWith("//")) { - part = part.substring(2); - } - - final DataUri dataUri = uriParser.parse(part); - if (dataUri == null) { - return null; - } - - final byte[] bytes = uriDecoder.decode(dataUri); - if (bytes == null) { - return null; - } - - return new ImageItem( - dataUri.contentType(), - new ByteArrayInputStream(bytes), - null - ); - } - - @Override - public void cancel(@NonNull String raw) { - // no op - } - - @NonNull - @Override - public Collection schemes() { - return Collections.singleton("data"); - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DrawableUtils.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DrawableUtils.java deleted file mode 100644 index f2aef636..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DrawableUtils.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.noties.markwon.il; - -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; - -abstract class DrawableUtils { - - static void intrinsicBounds(@NonNull Drawable drawable) { - drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); - } - - private DrawableUtils() {} -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/FileSchemeHandler.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/FileSchemeHandler.java deleted file mode 100644 index 437bbf7a..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/FileSchemeHandler.java +++ /dev/null @@ -1,109 +0,0 @@ -package ru.noties.markwon.il; - -import android.content.res.AssetManager; -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @since 2.0.0 - */ -public class FileSchemeHandler extends SchemeHandler { - - @NonNull - public static FileSchemeHandler createWithAssets(@NonNull AssetManager assetManager) { - return new FileSchemeHandler(assetManager); - } - - @NonNull - public static FileSchemeHandler create() { - return new FileSchemeHandler(null); - } - - private static final String FILE_ANDROID_ASSETS = "android_asset"; - - @Nullable - private final AssetManager assetManager; - - @SuppressWarnings("WeakerAccess") - FileSchemeHandler(@Nullable AssetManager assetManager) { - this.assetManager = assetManager; - } - - @Nullable - @Override - public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { - - final List segments = uri.getPathSegments(); - if (segments == null - || segments.size() == 0) { - // pointing to file & having no path segments is no use - return null; - } - - final ImageItem out; - - InputStream inputStream = null; - - final boolean assets = FILE_ANDROID_ASSETS.equals(segments.get(0)); - final String fileName = uri.getLastPathSegment(); - - if (assets) { - - // no handling of assets here if we have no assetsManager - if (assetManager != null) { - - final StringBuilder path = new StringBuilder(); - for (int i = 1, size = segments.size(); i < size; i++) { - if (i != 1) { - path.append('/'); - } - path.append(segments.get(i)); - } - // load assets - - try { - inputStream = assetManager.open(path.toString()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } else { - try { - inputStream = new BufferedInputStream(new FileInputStream(new File(uri.getPath()))); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - } - - if (inputStream != null) { - out = new ImageItem(fileName, inputStream, fileName); - } else { - out = null; - } - - return out; - } - - @Override - public void cancel(@NonNull String raw) { - // no op - } - - @NonNull - @Override - public Collection schemes() { - return Collections.singleton("file"); - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/GifMediaDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/GifMediaDecoder.java deleted file mode 100644 index 8342e7d5..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/GifMediaDecoder.java +++ /dev/null @@ -1,91 +0,0 @@ -package ru.noties.markwon.il; - -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import pl.droidsonroids.gif.GifDrawable; - -/** - * @since 1.1.0 - */ -@SuppressWarnings("WeakerAccess") -public class GifMediaDecoder extends MediaDecoder { - - protected static final String CONTENT_TYPE_GIF = "image/gif"; - protected static final String FILE_EXTENSION_GIF = ".gif"; - - @NonNull - public static GifMediaDecoder create(boolean autoPlayGif) { - return new GifMediaDecoder(autoPlayGif); - } - - private final boolean autoPlayGif; - - protected GifMediaDecoder(boolean autoPlayGif) { - this.autoPlayGif = autoPlayGif; - } - - @Override - public boolean canDecodeByContentType(@Nullable String contentType) { - return CONTENT_TYPE_GIF.equals(contentType); - } - - @Override - public boolean canDecodeByFileName(@NonNull String fileName) { - return fileName.endsWith(FILE_EXTENSION_GIF); - } - - @Nullable - @Override - public Drawable decode(@NonNull InputStream inputStream) { - - Drawable out = null; - - final byte[] bytes = readBytes(inputStream); - if (bytes != null) { - try { - out = newGifDrawable(bytes); - DrawableUtils.intrinsicBounds(out); - - if (!autoPlayGif) { - ((GifDrawable) out).pause(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - return out; - } - - @NonNull - protected Drawable newGifDrawable(@NonNull byte[] bytes) throws IOException { - return new GifDrawable(bytes); - } - - @Nullable - protected static byte[] readBytes(@NonNull InputStream stream) { - - byte[] out = null; - - try { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final int length = 1024 * 8; - final byte[] buffer = new byte[length]; - int read; - while ((read = stream.read(buffer, 0, length)) != -1) { - outputStream.write(buffer, 0, read); - } - out = outputStream.toByteArray(); - } catch (IOException e) { - e.printStackTrace(); - } - - return out; - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageItem.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageItem.java deleted file mode 100644 index 3ac9e9ec..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageItem.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.noties.markwon.il; - -import android.support.annotation.Nullable; - -import java.io.InputStream; - -/** - * @since 2.0.0 - */ -public class ImageItem { - - private final String contentType; - private final InputStream inputStream; - private final String fileName; - - public ImageItem( - @Nullable String contentType, - @Nullable InputStream inputStream, - @Nullable String fileName) { - this.contentType = contentType; - this.inputStream = inputStream; - this.fileName = fileName; - } - - @Nullable - public String contentType() { - return contentType; - } - - @Nullable - public InputStream inputStream() { - return inputStream; - } - - @Nullable - public String fileName() { - return fileName; - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageMediaDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageMediaDecoder.java deleted file mode 100644 index c36545ea..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/ImageMediaDecoder.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.noties.markwon.il; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.InputStream; - -/** - * This class can be used as the last {@link MediaDecoder} to _try_ to handle all rest cases. - * Here we just assume that supplied InputStream is of image type and try to decode it. - * - * @since 1.1.0 - */ -public class ImageMediaDecoder extends MediaDecoder { - - @NonNull - public static ImageMediaDecoder create(@NonNull Resources resources) { - return new ImageMediaDecoder(resources); - } - - private final Resources resources; - - @SuppressWarnings("WeakerAccess") - ImageMediaDecoder(Resources resources) { - this.resources = resources; - } - - @Override - public boolean canDecodeByContentType(@Nullable String contentType) { - return true; - } - - @Override - public boolean canDecodeByFileName(@NonNull String fileName) { - return true; - } - - @Nullable - @Override - public Drawable decode(@NonNull InputStream inputStream) { - - final Drawable out; - - // absolutely not optimal... thing - final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); - if (bitmap != null) { - out = new BitmapDrawable(resources, bitmap); - DrawableUtils.intrinsicBounds(out); - } else { - out = null; - } - - return out; - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/MediaDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/MediaDecoder.java deleted file mode 100644 index 294b716b..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/MediaDecoder.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.noties.markwon.il; - -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.InputStream; - -/** - * @since 1.1.0 - */ -public abstract class MediaDecoder { - - public abstract boolean canDecodeByContentType(@Nullable String contentType); - - public abstract boolean canDecodeByFileName(@NonNull String fileName); - - @Nullable - public abstract Drawable decode(@NonNull InputStream inputStream); -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/NetworkSchemeHandler.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/NetworkSchemeHandler.java deleted file mode 100644 index d87c4019..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/NetworkSchemeHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.noties.markwon.il; - -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import okhttp3.Call; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; - -/** - * @since 2.0.0 - */ -public class NetworkSchemeHandler extends SchemeHandler { - - @NonNull - public static NetworkSchemeHandler create(@NonNull OkHttpClient client) { - return new NetworkSchemeHandler(client); - } - - private static final String HEADER_CONTENT_TYPE = "Content-Type"; - - private final OkHttpClient client; - - @SuppressWarnings("WeakerAccess") - NetworkSchemeHandler(@NonNull OkHttpClient client) { - this.client = client; - } - - @Nullable - @Override - public ImageItem handle(@NonNull String raw, @NonNull Uri uri) { - - ImageItem out = null; - - final Request request = new Request.Builder() - .url(raw) - .tag(raw) - .build(); - - Response response = null; - try { - response = client.newCall(request).execute(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (response != null) { - final ResponseBody body = response.body(); - if (body != null) { - final InputStream inputStream = body.byteStream(); - if (inputStream != null) { - final String contentType = response.header(HEADER_CONTENT_TYPE); - out = new ImageItem(contentType, inputStream, null); - } - } - } - - return out; - } - - @Override - public void cancel(@NonNull String raw) { - final List calls = client.dispatcher().queuedCalls(); - if (calls != null) { - for (Call call : calls) { - if (!call.isCanceled()) { - if (raw.equals(call.request().tag())) { - call.cancel(); - } - } - } - } - } - - @NonNull - @Override - public Collection schemes() { - return Arrays.asList("http", "https"); - } -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/SchemeHandler.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/SchemeHandler.java deleted file mode 100644 index 6d8a44d1..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/SchemeHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.noties.markwon.il; - -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.util.Collection; - -/** - * @since 2.0.0 - */ -public abstract class SchemeHandler { - - @Nullable - public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri); - - public abstract void cancel(@NonNull String raw); - - /** - * Will be called only once during initialization, should return schemes that are - * handled by this handler - */ - @NonNull - public abstract Collection schemes(); -} diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/SvgMediaDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/SvgMediaDecoder.java deleted file mode 100644 index ff32255a..00000000 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/SvgMediaDecoder.java +++ /dev/null @@ -1,81 +0,0 @@ -package ru.noties.markwon.il; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.caverock.androidsvg.SVG; -import com.caverock.androidsvg.SVGParseException; - -import java.io.InputStream; - -/** - * @since 1.1.0 - */ -public class SvgMediaDecoder extends MediaDecoder { - - private static final String CONTENT_TYPE_SVG = "image/svg+xml"; - private static final String FILE_EXTENSION_SVG = ".svg"; - - @NonNull - public static SvgMediaDecoder create(@NonNull Resources resources) { - return new SvgMediaDecoder(resources); - } - - private final Resources resources; - - @SuppressWarnings("WeakerAccess") - SvgMediaDecoder(Resources resources) { - this.resources = resources; - } - - @Override - public boolean canDecodeByContentType(@Nullable String contentType) { - return contentType != null && contentType.startsWith(CONTENT_TYPE_SVG); - } - - @Override - public boolean canDecodeByFileName(@NonNull String fileName) { - return fileName.endsWith(FILE_EXTENSION_SVG); - } - - @Nullable - @Override - public Drawable decode(@NonNull InputStream inputStream) { - - final Drawable out; - - SVG svg = null; - try { - svg = SVG.getFromInputStream(inputStream); - } catch (SVGParseException e) { - e.printStackTrace(); - } - - if (svg == null) { - out = null; - } else { - - final float w = svg.getDocumentWidth(); - final float h = svg.getDocumentHeight(); - final float density = resources.getDisplayMetrics().density; - - final int width = (int) (w * density + .5F); - final int height = (int) (h * density + .5F); - - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); - final Canvas canvas = new Canvas(bitmap); - canvas.scale(density, density); - svg.renderToCanvas(canvas); - - out = new BitmapDrawable(resources, bitmap); - DrawableUtils.intrinsicBounds(out); - } - - return out; - } -} diff --git a/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriParserTest.java b/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriParserTest.java deleted file mode 100644 index 6de01af5..00000000 --- a/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriParserTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package ru.noties.markwon.il; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -@RunWith(RobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public class DataUriParserTest { - - private DataUriParser.Impl impl; - - @Before - public void before() { - impl = new DataUriParser.Impl(); - } - - @Test - public void test() { - - final Map data = new LinkedHashMap() {{ - put(",", new DataUri(null, false, null)); - put("image/svg+xml;base64,!@#$%^&*(", new DataUri("image/svg+xml", true, "!@#$%^&*(")); - put("text/vnd-example+xyz;foo=bar;base64,R0lGODdh", new DataUri("text/vnd-example+xyz", true, "R0lGODdh")); - put("text/plain;charset=UTF-8;page=21,the%20data:1234,5678", new DataUri("text/plain", false, "the%20data:1234,5678")); - }}; - - for (Map.Entry entry : data.entrySet()) { - assertEquals(entry.getKey(), entry.getValue(), impl.parse(entry.getKey())); - } - } - - @Test - public void data_new_lines_are_ignored() { - - final String input = "image/png;base64,iVBORw0KGgoAAA\n" + - "ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4\n" + - "//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU\n" + - "5ErkJggg=="; - - assertEquals( - new DataUri("image/png", true, "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), - impl.parse(input) - ); - } - - @Test - public void no_comma_returns_null() { - - final String[] inputs = { - "", - "what-ever", - ";;;;;;;", - "some crazy data" - }; - - for (String input : inputs) { - assertNull(input, impl.parse(input)); - } - } - - @Test - public void two_commas() { - final String input = ",,"; // <- second one would be considered data... - assertEquals( - input, - new DataUri(null, false, ","), - impl.parse(input) - ); - } - - @Test - public void more_commas() { - final String input = "first,second,third"; // <- first is just a value (will be ignored) - assertEquals( - input, - new DataUri(null, false, "second,third"), - impl.parse(input) - ); - } - - @Test - public void base64_no_content_type() { - final String input = ";base64,12345"; - assertEquals( - input, - new DataUri(null, true, "12345"), - impl.parse(input) - ); - } - - @Test - public void not_base64_no_content_type() { - final String input = ",qweRTY"; - assertEquals( - input, - new DataUri(null, false, "qweRTY"), - impl.parse(input) - ); - } - - @Test - public void content_type_data_no_base64() { - final String input = "image/png,aSdFg"; - assertEquals( - input, - new DataUri("image/png", false, "aSdFg"), - impl.parse(input) - ); - } -} \ No newline at end of file diff --git a/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriSchemeHandlerTest.java b/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriSchemeHandlerTest.java deleted file mode 100644 index 1473744a..00000000 --- a/markwon-image-loader/src/test/java/ru/noties/markwon/il/DataUriSchemeHandlerTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package ru.noties.markwon.il; - -import android.net.Uri; -import android.support.annotation.NonNull; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -@RunWith(RobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public class DataUriSchemeHandlerTest { - - private DataUriSchemeHandler handler; - - @Before - public void before() { - handler = DataUriSchemeHandler.create(); - } - - @Test - public void scheme_specific_part_is_empty() { - assertNull(handler.handle("data:", Uri.parse("data:"))); - } - - @Test - public void data_uri_is_empty() { - assertNull(handler.handle("data://whatever", Uri.parse("data://whatever"))); - } - - @Test - public void no_data() { - assertNull(handler.handle("data://,", Uri.parse("data://,"))); - } - - @Test - public void correct() { - - final class Item { - - final String contentType; - final String data; - - Item(String contentType, String data) { - this.contentType = contentType; - this.data = data; - } - } - - final Map expected = new HashMap() {{ - put("data://text/plain;,123", new Item("text/plain", "123")); - put("data://image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123")); - }}; - - for (Map.Entry entry : expected.entrySet()) { - final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey())); - assertNotNull(entry.getKey(), item); - assertEquals(entry.getKey(), entry.getValue().contentType, item.contentType()); - assertEquals(entry.getKey(), entry.getValue().data, readStream(item.inputStream())); - } - } - - @Test - public void correct_real() { - - final class Item { - - final String contentType; - final String data; - - Item(String contentType, String data) { - this.contentType = contentType; - this.data = data; - } - } - - final Map expected = new HashMap() {{ - put("data:text/plain;,123", new Item("text/plain", "123")); - put("data:image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123")); - }}; - - for (Map.Entry entry : expected.entrySet()) { - final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey())); - assertNotNull(entry.getKey(), item); - assertEquals(entry.getKey(), entry.getValue().contentType, item.contentType()); - assertEquals(entry.getKey(), entry.getValue().data, readStream(item.inputStream())); - } - } - - @NonNull - private static String readStream(@NonNull InputStream stream) { - try { - final Scanner scanner = new Scanner(stream, "UTF-8").useDelimiter("\\A"); - return scanner.hasNext() - ? scanner.next() - : ""; - } catch (Throwable t) { - throw new RuntimeException(t); - } - } -} \ No newline at end of file diff --git a/markwon-syntax-highlight/src/main/java/ru/noties/markwon/syntax/Prism4jThemeDarkula.java b/markwon-syntax-highlight/src/main/java/ru/noties/markwon/syntax/Prism4jThemeDarkula.java index 9a941951..13bfe48b 100644 --- a/markwon-syntax-highlight/src/main/java/ru/noties/markwon/syntax/Prism4jThemeDarkula.java +++ b/markwon-syntax-highlight/src/main/java/ru/noties/markwon/syntax/Prism4jThemeDarkula.java @@ -16,6 +16,10 @@ public class Prism4jThemeDarkula extends Prism4jThemeBase { return new Prism4jThemeDarkula(0xFF2d2d2d); } + /** + * @param background color + * @since 3.0.0 + */ @NonNull public static Prism4jThemeDarkula create(@ColorInt int background) { return new Prism4jThemeDarkula(background); diff --git a/markwon/build.gradle b/markwon/build.gradle index fc3dc8ff..3cb54118 100644 --- a/markwon/build.gradle +++ b/markwon/build.gradle @@ -15,9 +15,6 @@ android { dependencies { - api project(':markwon-html-parser-api') - api project(':markwon-html-parser-impl') - deps.with { api it['support-annotations'] api it['commonmark'] diff --git a/markwon/src/main/java/ru/noties/markwon/MarkwonConfiguration.java b/markwon/src/main/java/ru/noties/markwon/MarkwonConfiguration.java index 1f6e2216..7c9fad92 100644 --- a/markwon/src/main/java/ru/noties/markwon/MarkwonConfiguration.java +++ b/markwon/src/main/java/ru/noties/markwon/MarkwonConfiguration.java @@ -3,12 +3,12 @@ package ru.noties.markwon; import android.content.Context; import android.support.annotation.NonNull; -import ru.noties.markwon.html.api.MarkwonHtmlParser; +import ru.noties.markwon.html.MarkwonHtmlParser; +import ru.noties.markwon.html.MarkwonHtmlRenderer; import ru.noties.markwon.image.AsyncDrawableLoader; import ru.noties.markwon.image.AsyncDrawableLoaderNoOp; import ru.noties.markwon.renderer.ImageSizeResolver; import ru.noties.markwon.renderer.ImageSizeResolverDef; -import ru.noties.markwon.renderer.html2.MarkwonHtmlRenderer; import ru.noties.markwon.spans.LinkSpan; import ru.noties.markwon.spans.MarkwonTheme; @@ -37,7 +37,6 @@ public class MarkwonConfiguration { private final UrlProcessor urlProcessor; private final ImageSizeResolver imageSizeResolver; private final SpannableFactory factory; // @since 1.1.0 - private final boolean softBreakAddsNewLine; // @since 1.1.1 private final MarkwonHtmlParser htmlParser; // @since 2.0.0 private final MarkwonHtmlRenderer htmlRenderer; // @since 2.0.0 private final boolean htmlAllowNonClosedTags; // @since 2.0.0 @@ -50,7 +49,6 @@ public class MarkwonConfiguration { this.urlProcessor = builder.urlProcessor; this.imageSizeResolver = builder.imageSizeResolver; this.factory = builder.factory; - this.softBreakAddsNewLine = builder.softBreakAddsNewLine; this.htmlParser = builder.htmlParser; this.htmlRenderer = builder.htmlRenderer; this.htmlAllowNonClosedTags = builder.htmlAllowNonClosedTags; @@ -99,15 +97,6 @@ public class MarkwonConfiguration { return factory; } - /** - * @return a flag indicating if soft break should be treated as a hard - * break and thus adding a new line instead of adding a white space - * @since 1.1.1 - */ - public boolean softBreakAddsNewLine() { - return softBreakAddsNewLine; - } - /** * @since 2.0.0 */ @@ -143,7 +132,6 @@ public class MarkwonConfiguration { private UrlProcessor urlProcessor; private ImageSizeResolver imageSizeResolver; private SpannableFactory factory; // @since 1.1.0 - private boolean softBreakAddsNewLine; // @since 1.1.1 private MarkwonHtmlParser htmlParser; // @since 2.0.0 private MarkwonHtmlRenderer htmlRenderer; // @since 2.0.0 private boolean htmlAllowNonClosedTags; // @since 2.0.0 @@ -161,7 +149,6 @@ public class MarkwonConfiguration { this.urlProcessor = configuration.urlProcessor; this.imageSizeResolver = configuration.imageSizeResolver; this.factory = configuration.factory; - this.softBreakAddsNewLine = configuration.softBreakAddsNewLine; this.htmlParser = configuration.htmlParser; this.htmlRenderer = configuration.htmlRenderer; this.htmlAllowNonClosedTags = configuration.htmlAllowNonClosedTags; @@ -203,19 +190,6 @@ public class MarkwonConfiguration { return this; } - /** - * @param softBreakAddsNewLine a flag indicating if soft break should be treated as a hard - * break and thus adding a new line instead of adding a white space - * @return self - * @see spec - * @since 1.1.1 - */ - @NonNull - public Builder softBreakAddsNewLine(boolean softBreakAddsNewLine) { - this.softBreakAddsNewLine = softBreakAddsNewLine; - return this; - } - /** * @since 2.0.0 */ @@ -276,17 +250,12 @@ public class MarkwonConfiguration { // @since 2.0.0 if (htmlParser == null) { - try { - // if impl artifact was excluded -> fallback to no-op implementation - htmlParser = ru.noties.markwon.html.impl.MarkwonHtmlParserImpl.create(); - } catch (Throwable t) { - htmlParser = MarkwonHtmlParser.noOp(); - } + htmlParser = MarkwonHtmlParser.noOp(); } // @since 2.0.0 if (htmlRenderer == null) { - htmlRenderer = MarkwonHtmlRenderer.create(); + htmlRenderer = MarkwonHtmlRenderer.noOp(); } return new MarkwonConfiguration(this); diff --git a/markwon/src/main/java/ru/noties/markwon/SpannableFactory.java b/markwon/src/main/java/ru/noties/markwon/SpannableFactory.java index 13a64cf4..3efec181 100644 --- a/markwon/src/main/java/ru/noties/markwon/SpannableFactory.java +++ b/markwon/src/main/java/ru/noties/markwon/SpannableFactory.java @@ -63,16 +63,4 @@ public interface SpannableFactory { @NonNull MarkwonTheme theme, @NonNull String destination, @NonNull LinkSpan.Resolver resolver); - - // Currently used by HTML parser - @Nullable - Object superScript(@NonNull MarkwonTheme theme); - - // Currently used by HTML parser - @Nullable - Object subScript(@NonNull MarkwonTheme theme); - - // Currently used by HTML parser - @Nullable - Object underline(); } diff --git a/markwon/src/main/java/ru/noties/markwon/SpannableFactoryDef.java b/markwon/src/main/java/ru/noties/markwon/SpannableFactoryDef.java index 21074983..75726b2a 100644 --- a/markwon/src/main/java/ru/noties/markwon/SpannableFactoryDef.java +++ b/markwon/src/main/java/ru/noties/markwon/SpannableFactoryDef.java @@ -118,21 +118,4 @@ public class SpannableFactoryDef implements SpannableFactory { public Object link(@NonNull MarkwonTheme theme, @NonNull String destination, @NonNull LinkSpan.Resolver resolver) { return new LinkSpan(theme, destination, resolver); } - - @Nullable - @Override - public Object superScript(@NonNull MarkwonTheme theme) { - return new SuperScriptSpan(theme); - } - - @Override - public Object subScript(@NonNull MarkwonTheme theme) { - return new SubScriptSpan(theme); - } - - @Nullable - @Override - public Object underline() { - return new UnderlineSpan(); - } } diff --git a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java b/markwon/src/main/java/ru/noties/markwon/html/HtmlTag.java similarity index 98% rename from markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java rename to markwon/src/main/java/ru/noties/markwon/html/HtmlTag.java index f3245876..fbe417e9 100644 --- a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java +++ b/markwon/src/main/java/ru/noties/markwon/html/HtmlTag.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.html.api; +package ru.noties.markwon.html; import android.support.annotation.NonNull; import android.support.annotation.Nullable; diff --git a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParser.java b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParser.java similarity index 92% rename from markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParser.java rename to markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParser.java index 8d168a72..01bea86a 100644 --- a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParser.java +++ b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParser.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.html.api; +package ru.noties.markwon.html; import android.support.annotation.NonNull; @@ -34,7 +34,7 @@ public abstract class MarkwonHtmlParser { * If you wish to keep them open (do not force close at the end of a * document pass here {@link HtmlTag#NO_END}. Later non-closed tags * can be detected by calling {@link HtmlTag#isClosed()} - * @param action {@link FlushAction} to be called with resulting tags ({@link ru.noties.markwon.html.api.HtmlTag.Inline}) + * @param action {@link FlushAction} to be called with resulting tags ({@link HtmlTag.Inline}) */ public abstract void flushInlineTags( int documentLength, @@ -49,7 +49,7 @@ public abstract class MarkwonHtmlParser { * If you wish to keep them open (do not force close at the end of a * document pass here {@link HtmlTag#NO_END}. Later non-closed tags * can be detected by calling {@link HtmlTag#isClosed()} - * @param action {@link FlushAction} to be called with resulting tags ({@link ru.noties.markwon.html.api.HtmlTag.Block}) + * @param action {@link FlushAction} to be called with resulting tags ({@link HtmlTag.Block}) */ public abstract void flushBlockTags( int documentLength, diff --git a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParserNoOp.java b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParserNoOp.java similarity index 95% rename from markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParserNoOp.java rename to markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParserNoOp.java index 0a024865..3b49528a 100644 --- a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/MarkwonHtmlParserNoOp.java +++ b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlParserNoOp.java @@ -1,4 +1,4 @@ -package ru.noties.markwon.html.api; +package ru.noties.markwon.html; import android.support.annotation.NonNull; diff --git a/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRenderer.java b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRenderer.java new file mode 100644 index 00000000..9e9d222f --- /dev/null +++ b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRenderer.java @@ -0,0 +1,30 @@ +package ru.noties.markwon.html; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import ru.noties.markwon.MarkwonConfiguration; +import ru.noties.markwon.SpannableBuilder; + +/** + * @since 2.0.0 + */ +public abstract class MarkwonHtmlRenderer { + + /** + * @since 3.0.0 + */ + @NonNull + public static MarkwonHtmlRenderer noOp() { + return new MarkwonHtmlRendererNoOp(); + } + + public abstract void render( + @NonNull MarkwonConfiguration configuration, + @NonNull SpannableBuilder builder, + @NonNull MarkwonHtmlParser parser + ); + + @Nullable + public abstract TagHandler tagHandler(@NonNull String tagName); +} diff --git a/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRendererNoOp.java b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRendererNoOp.java new file mode 100644 index 00000000..7df5027c --- /dev/null +++ b/markwon/src/main/java/ru/noties/markwon/html/MarkwonHtmlRendererNoOp.java @@ -0,0 +1,21 @@ +package ru.noties.markwon.html; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import ru.noties.markwon.MarkwonConfiguration; +import ru.noties.markwon.SpannableBuilder; + +class MarkwonHtmlRendererNoOp extends MarkwonHtmlRenderer { + + @Override + public void render(@NonNull MarkwonConfiguration configuration, @NonNull SpannableBuilder builder, @NonNull MarkwonHtmlParser parser) { + + } + + @Nullable + @Override + public TagHandler tagHandler(@NonNull String tagName) { + return null; + } +} diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java b/markwon/src/main/java/ru/noties/markwon/html/TagHandler.java similarity index 91% rename from markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java rename to markwon/src/main/java/ru/noties/markwon/html/TagHandler.java index bdf9b134..50af33d8 100644 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java +++ b/markwon/src/main/java/ru/noties/markwon/html/TagHandler.java @@ -1,10 +1,9 @@ -package ru.noties.markwon.renderer.html2.tag; +package ru.noties.markwon.html; import android.support.annotation.NonNull; import ru.noties.markwon.MarkwonConfiguration; import ru.noties.markwon.SpannableBuilder; -import ru.noties.markwon.html.api.HtmlTag; public abstract class TagHandler { diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java deleted file mode 100644 index b66045e6..00000000 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java +++ /dev/null @@ -1,101 +0,0 @@ -package ru.noties.markwon.renderer.html2; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import ru.noties.markwon.SpannableBuilder; -import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.MarkwonHtmlParser; -import ru.noties.markwon.renderer.html2.tag.BlockquoteHandler; -import ru.noties.markwon.renderer.html2.tag.EmphasisHandler; -import ru.noties.markwon.renderer.html2.tag.HeadingHandler; -import ru.noties.markwon.renderer.html2.tag.ImageHandler; -import ru.noties.markwon.renderer.html2.tag.LinkHandler; -import ru.noties.markwon.renderer.html2.tag.ListHandler; -import ru.noties.markwon.renderer.html2.tag.StrikeHandler; -import ru.noties.markwon.renderer.html2.tag.StrongEmphasisHandler; -import ru.noties.markwon.renderer.html2.tag.SubScriptHandler; -import ru.noties.markwon.renderer.html2.tag.SuperScriptHandler; -import ru.noties.markwon.renderer.html2.tag.TagHandler; -import ru.noties.markwon.renderer.html2.tag.UnderlineHandler; - -/** - * @since 2.0.0 - */ -public abstract class MarkwonHtmlRenderer { - - public abstract void render( - @NonNull MarkwonConfiguration configuration, - @NonNull SpannableBuilder builder, - @NonNull MarkwonHtmlParser parser - ); - - @Nullable - public abstract TagHandler tagHandler(@NonNull String tagName); - - @NonNull - public static MarkwonHtmlRenderer create() { - return builderWithDefaults().build(); - } - - @NonNull - public static Builder builderWithDefaults() { - - final EmphasisHandler emphasisHandler = new EmphasisHandler(); - final StrongEmphasisHandler strongEmphasisHandler = new StrongEmphasisHandler(); - final StrikeHandler strikeHandler = new StrikeHandler(); - final UnderlineHandler underlineHandler = new UnderlineHandler(); - final ListHandler listHandler = new ListHandler(); - - return builder() - .handler("i", emphasisHandler) - .handler("em", emphasisHandler) - .handler("cite", emphasisHandler) - .handler("dfn", emphasisHandler) - .handler("b", strongEmphasisHandler) - .handler("strong", strongEmphasisHandler) - .handler("sup", new SuperScriptHandler()) - .handler("sub", new SubScriptHandler()) - .handler("u", underlineHandler) - .handler("ins", underlineHandler) - .handler("del", strikeHandler) - .handler("s", strikeHandler) - .handler("strike", strikeHandler) - .handler("a", new LinkHandler()) - .handler("ul", listHandler) - .handler("ol", listHandler) - .handler("img", ImageHandler.create()) - .handler("blockquote", new BlockquoteHandler()) - .handler("h1", new HeadingHandler(1)) - .handler("h2", new HeadingHandler(2)) - .handler("h3", new HeadingHandler(3)) - .handler("h4", new HeadingHandler(4)) - .handler("h5", new HeadingHandler(5)) - .handler("h6", new HeadingHandler(6)); - } - - @NonNull - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private final Map tagHandlers = new HashMap<>(2); - - public Builder handler(@NonNull String tagName, @NonNull TagHandler tagHandler) { - tagHandlers.put(tagName.toLowerCase(Locale.US), tagHandler); - return this; - } - - @NonNull - public MarkwonHtmlRenderer build() { - return new MarkwonHtmlRendererImpl(Collections.unmodifiableMap(tagHandlers)); - } - } -} diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java deleted file mode 100644 index cc34f55b..00000000 --- a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java +++ /dev/null @@ -1,88 +0,0 @@ -package ru.noties.markwon.renderer.html2; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.util.List; -import java.util.Map; - -import ru.noties.markwon.SpannableBuilder; -import ru.noties.markwon.MarkwonConfiguration; -import ru.noties.markwon.html.api.HtmlTag; -import ru.noties.markwon.html.api.MarkwonHtmlParser; -import ru.noties.markwon.renderer.html2.tag.TagHandler; - -class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer { - - private final Map tagHandlers; - - MarkwonHtmlRendererImpl(@NonNull Map tagHandlers) { - this.tagHandlers = tagHandlers; - } - - @Override - public void render( - @NonNull final MarkwonConfiguration configuration, - @NonNull final SpannableBuilder builder, - @NonNull MarkwonHtmlParser parser) { - - final int end; - if (!configuration.htmlAllowNonClosedTags()) { - end = HtmlTag.NO_END; - } else { - end = builder.length(); - } - - parser.flushInlineTags(end, new MarkwonHtmlParser.FlushAction() { - @Override - public void apply(@NonNull List tags) { - - TagHandler handler; - - for (HtmlTag.Inline inline : tags) { - - // if tag is not closed -> do not render - if (!inline.isClosed()) { - continue; - } - - handler = tagHandler(inline.name()); - if (handler != null) { - handler.handle(configuration, builder, inline); - } - } - } - }); - - parser.flushBlockTags(end, new MarkwonHtmlParser.FlushAction() { - @Override - public void apply(@NonNull List tags) { - - TagHandler handler; - - for (HtmlTag.Block block : tags) { - - if (!block.isClosed()) { - continue; - } - - handler = tagHandler(block.name()); - if (handler != null) { - handler.handle(configuration, builder, block); - } else { - // see if any of children can be handled - apply(block.children()); - } - } - } - }); - - parser.reset(); - } - - @Nullable - @Override - public TagHandler tagHandler(@NonNull String tagName) { - return tagHandlers.get(tagName); - } -} diff --git a/markwon/src/test/java/ru/noties/markwon/renderer/MarkwonConfigurationTest.java b/markwon/src/test/java/ru/noties/markwon/renderer/MarkwonConfigurationTest.java index 108df62d..11f539b3 100644 --- a/markwon/src/test/java/ru/noties/markwon/renderer/MarkwonConfigurationTest.java +++ b/markwon/src/test/java/ru/noties/markwon/renderer/MarkwonConfigurationTest.java @@ -7,7 +7,7 @@ import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.SyntaxHighlight; import ru.noties.markwon.UrlProcessor; import ru.noties.markwon.html.api.MarkwonHtmlParser; -import ru.noties.markwon.renderer.html2.MarkwonHtmlRenderer; +import ru.noties.markwon.html.MarkwonHtmlRenderer; import ru.noties.markwon.image.AsyncDrawable; import ru.noties.markwon.spans.LinkSpan; import ru.noties.markwon.spans.MarkwonTheme; diff --git a/settings.gradle b/settings.gradle index 3a1678e4..ca458b18 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'MarkwonProject' include ':app', ':markwon', ':markwon-view', ':sample-custom-extension', ':sample-latex-math', ':markwon-image-svg', ':markwon-image-gif', - ':markwon-syntax-highlight', ':markwon-html-parser-api', ':markwon-html-parser-impl' + ':markwon-syntax-highlight', ':markwon-html'