From d101cddf0fb57f4c28e1adbdf481a8aa26acaf6d Mon Sep 17 00:00:00 2001 From: scria1000 <91804886+scria1000@users.noreply.github.com> Date: Thu, 9 Dec 2021 13:23:02 +0300 Subject: [PATCH] Make Superscript parsing proper Do this without relying converting to tags. --- app/build.gradle | 1 - .../activities/CommentActivity.java | 21 ++-- .../activities/FullMarkdownActivity.java | 22 +--- .../ViewSubredditDetailActivity.java | 2 + .../activities/ViewUserDetailActivity.java | 2 + .../activities/WikiActivity.java | 13 +- .../CommentsListingRecyclerViewAdapter.java | 21 +--- .../adapters/CommentsRecyclerViewAdapter.java | 14 +-- .../adapters/MessageRecyclerViewAdapter.java | 22 +--- .../PostDetailRecyclerViewAdapter.java | 13 +- ...vateMessagesDetailRecyclerViewAdapter.java | 13 +- .../adapters/RulesRecyclerViewAdapter.java | 14 +-- .../fragments/SidebarFragment.java | 14 +-- .../markdown/SuperScriptSpan.java | 25 ++++ .../markdown/Superscript.java | 31 +++++ .../markdown/SuperscriptInlineProcessor.java | 32 ----- .../markdown/SuperscriptParser.java | 117 ++++++++++++++++++ .../markdown/SuperscriptPlugin.java | 38 ++++++ .../infinityforreddit/utils/Utils.java | 44 ------- 19 files changed, 268 insertions(+), 191 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperScriptSpan.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/Superscript.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptParser.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptPlugin.java diff --git a/app/build.gradle b/app/build.gradle index cb019542..1779752f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,7 +153,6 @@ dependencies { implementation "io.noties.markwon:linkify:$markwonVersion" implementation "io.noties.markwon:recycler-table:$markwonVersion" implementation "io.noties.markwon:simple-ext:$markwonVersion" - implementation "io.noties.markwon:html:$markwonVersion" implementation "io.noties.markwon:inline-parser:$markwonVersion" implementation 'com.atlassian.commonmark:commonmark-ext-gfm-tables:0.14.0' implementation 'me.saket:better-link-movement-method:2.2.0' diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java index 7680f2fd..4a06c3a7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java @@ -50,8 +50,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -71,8 +70,8 @@ import ml.docilealligator.infinityforreddit.comment.SendComment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; @@ -166,18 +165,16 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA int linkColor = mCustomThemeWrapper.getLinkColor(); Markwon markwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override @@ -220,18 +217,16 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA contentMarkdownRecyclerView.setNestedScrollingEnabled(false); Markwon postBodyMarkwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java index acd1713c..52c053c7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java @@ -3,14 +3,10 @@ package ml.docilealligator.infinityforreddit.activities; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; -import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.text.TextPaint; -import android.text.style.ClickableSpan; import android.text.util.Linkify; import android.view.Menu; import android.view.MenuItem; @@ -33,9 +29,6 @@ import org.commonmark.ext.gfm.tables.TableBlock; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import javax.inject.Inject; import javax.inject.Named; @@ -46,8 +39,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -62,10 +54,8 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; -import ml.docilealligator.infinityforreddit.utils.Utils; public class FullMarkdownActivity extends BaseActivity { @@ -139,18 +129,16 @@ public class FullMarkdownActivity extends BaseActivity { int linkColor = mCustomThemeWrapper.getLinkColor(); Markwon markwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java index 4402434f..dfe4970f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java @@ -72,6 +72,7 @@ import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -386,6 +387,7 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp Markwon markwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); })) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java index f733b122..9a1a120a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java @@ -74,6 +74,7 @@ import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -381,6 +382,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele Markwon markwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); })) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java index 755a1c7b..04619b48 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java @@ -44,8 +44,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -64,7 +63,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.utils.JSONUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.utils.Utils; @@ -163,18 +162,16 @@ public class WikiActivity extends BaseActivity { int linkColor = mCustomThemeWrapper.getLinkColor(); markwon = Markwon.builder(this) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java index 40bce0d6..199cd48a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java @@ -3,14 +3,9 @@ package ml.docilealligator.infinityforreddit.adapters; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.ColorStateList; -import android.graphics.Color; import android.graphics.PorterDuff; import android.net.Uri; import android.os.Bundle; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextPaint; -import android.text.style.ClickableSpan; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; @@ -32,8 +27,6 @@ import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import butterknife.BindView; import butterknife.ButterKnife; @@ -42,8 +35,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -64,10 +56,9 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.CommentIndentationView; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; @@ -124,18 +115,16 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java index 6e6d18d5..ac7e46ef 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java @@ -42,9 +42,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; -import io.noties.markwon.inlineparser.BackslashInlineProcessor; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -67,7 +65,7 @@ import ml.docilealligator.infinityforreddit.customviews.CommentIndentationView; import ml.docilealligator.infinityforreddit.customviews.SpoilerOnClickTextView; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.post.Post; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; @@ -163,18 +161,16 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java index 7560aab4..0eba99f3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/MessageRecyclerViewAdapter.java @@ -3,13 +3,8 @@ package ml.docilealligator.infinityforreddit.adapters; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; -import android.graphics.Color; import android.net.Uri; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextPaint; import android.text.method.LinkMovementMethod; -import android.text.style.ClickableSpan; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; @@ -24,8 +19,6 @@ import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import butterknife.BindView; import butterknife.ButterKnife; @@ -34,8 +27,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -47,12 +39,10 @@ import ml.docilealligator.infinityforreddit.activities.ViewPrivateMessagesActivi import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SpoilerSpan; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.message.FetchMessage; import ml.docilealligator.infinityforreddit.message.Message; import ml.docilealligator.infinityforreddit.message.ReadMessage; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; -import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; public class MessageRecyclerViewAdapter extends PagedListAdapter { @@ -108,18 +98,16 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java index b436a1ec..dd1172a8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java @@ -67,8 +67,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -106,7 +105,7 @@ import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFi import ml.docilealligator.infinityforreddit.customviews.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment; import ml.docilealligator.infinityforreddit.markdown.SpoilerParserPlugin; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.post.Post; import ml.docilealligator.infinityforreddit.post.PostPagingSource; import ml.docilealligator.infinityforreddit.utils.APIUtils; @@ -227,18 +226,16 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java index 180b74be..8d785c4c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PrivateMessagesDetailRecyclerViewAdapter.java @@ -27,8 +27,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -39,9 +38,9 @@ import ml.docilealligator.infinityforreddit.activities.LinkResolverActivity; import ml.docilealligator.infinityforreddit.activities.ViewPrivateMessagesActivity; import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.message.Message; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; import ml.docilealligator.infinityforreddit.utils.Utils; public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapter { @@ -72,18 +71,16 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt mAccountName = accountName; mMarkwon = Markwon.builder(viewPrivateMessagesActivity) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java index 13e5e6a1..a5da4780 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java @@ -22,8 +22,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -35,8 +34,7 @@ import ml.docilealligator.infinityforreddit.Rule; import ml.docilealligator.infinityforreddit.activities.LinkResolverActivity; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; -import ml.docilealligator.infinityforreddit.utils.Utils; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; public class RulesRecyclerViewAdapter extends RecyclerView.Adapter { private Markwon markwon; @@ -47,18 +45,16 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java index a7116540..474eaed4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java @@ -34,8 +34,7 @@ import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.html.HtmlPlugin; -import io.noties.markwon.html.tag.SuperScriptHandler; +import io.noties.markwon.inlineparser.AutolinkInlineProcessor; import io.noties.markwon.inlineparser.BangInlineProcessor; import io.noties.markwon.inlineparser.HtmlInlineProcessor; import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; @@ -55,11 +54,10 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.CopyTextBottomS import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; +import ml.docilealligator.infinityforreddit.markdown.SuperscriptPlugin; import ml.docilealligator.infinityforreddit.subreddit.FetchSubredditData; import ml.docilealligator.infinityforreddit.subreddit.SubredditData; import ml.docilealligator.infinityforreddit.subreddit.SubredditViewModel; -import ml.docilealligator.infinityforreddit.markdown.SuperscriptInlineProcessor; -import ml.docilealligator.infinityforreddit.utils.Utils; import retrofit2.Retrofit; public class SidebarFragment extends Fragment { @@ -111,18 +109,16 @@ public class SidebarFragment extends Fragment { Markwon markwon = Markwon.builder(activity) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { + plugin.excludeInlineProcessor(AutolinkInlineProcessor.class); plugin.excludeInlineProcessor(HtmlInlineProcessor.class); plugin.excludeInlineProcessor(BangInlineProcessor.class); - plugin.addInlineProcessor(new SuperscriptInlineProcessor()); - })) - .usePlugin(HtmlPlugin.create(plugin -> { - plugin.excludeDefaults(true).addHandler(new SuperScriptHandler()); })) + .usePlugin(SuperscriptPlugin.create()) .usePlugin(new AbstractMarkwonPlugin() { @NonNull @Override public String processMarkdown(@NonNull String markdown) { - return super.processMarkdown(Utils.fixSuperScript(markdown)); + return super.processMarkdown(markdown); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperScriptSpan.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperScriptSpan.java new file mode 100644 index 00000000..015cf8df --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperScriptSpan.java @@ -0,0 +1,25 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import android.text.TextPaint; +import android.text.style.MetricAffectingSpan; + +import androidx.annotation.NonNull; + +public class SuperScriptSpan extends MetricAffectingSpan { + private static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F; + + @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() * SCRIPT_DEF_TEXT_SIZE_RATIO); + paint.baselineShift += (int) (paint.ascent() / 2); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/Superscript.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/Superscript.java new file mode 100644 index 00000000..c45a3f3c --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/Superscript.java @@ -0,0 +1,31 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import org.commonmark.node.CustomNode; +import org.commonmark.node.Visitor; + +public class Superscript extends CustomNode { + private String literal; + private int level; + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + public String getLiteral() { + return literal; + } + + public void setLiteral(String literal) { + this.literal = literal; + } + + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java deleted file mode 100644 index 27f4d1e4..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptInlineProcessor.java +++ /dev/null @@ -1,32 +0,0 @@ -package ml.docilealligator.infinityforreddit.markdown; - -import androidx.annotation.Nullable; - -import org.commonmark.node.HtmlInline; -import org.commonmark.node.Node; - -import java.util.regex.Pattern; - -import io.noties.markwon.inlineparser.InlineProcessor; - -public class SuperscriptInlineProcessor extends InlineProcessor { - private static final Pattern HTML_TAG = Pattern.compile("", Pattern.CASE_INSENSITIVE); - - @Override - public char specialCharacter() { - return '<'; - } - - @Nullable - @Override - protected Node parse() { - String m = match(HTML_TAG); - if (m != null) { - HtmlInline node = new HtmlInline(); - node.setLiteral(m); - return node; - } else { - return null; - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptParser.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptParser.java new file mode 100644 index 00000000..7edc86e0 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptParser.java @@ -0,0 +1,117 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import androidx.annotation.Nullable; + +import org.commonmark.node.Node; + +import io.noties.markwon.inlineparser.InlineProcessor; + +public class SuperscriptParser extends InlineProcessor { + + private int level = 0; + + @Override + public char specialCharacter() { + return '^'; + } + + @Nullable + @Override + protected Node parse() { + Node node = parseSuperscript(level); + if (node != null) { + return nestSuperscriptNodes(node); + } + level = 0; + return null; + } + + private Node nestSuperscriptNodes(Node node) { + if (block.getLastChild() instanceof Superscript + && peek() != '^') { + var current = block.getLastChild(); + current.appendChild(node); + Node tmp = null; + while (true) { + tmp = current; + current = current.getPrevious(); + if (current instanceof Superscript) { + current.appendChild(tmp); + } else { + break; + } + } + level = 0; + return tmp; + } else { + level++; + return node; + } + } + + // Hopefully we've handled edge cases + private Superscript parseSuperscript(int level) { + int start = index; + int length = input.length(); + int caret_pos = -1; + int nCarets = 0; + int new_lines = 0; + boolean hasBracket = false; + for (int i = start; i < length; i++) { + char currentChar = input.charAt(i); + if (currentChar == '\n') { + new_lines++; + if (new_lines > 0 && nCarets > 0 || hasBracket) { + break; + } + } else if ((i + 1) < length + && nCarets == 0 + && !hasBracket + && !(i > 0 && input.charAt(i - 1) == '\\') + && currentChar == '^' + && !Character.isWhitespace(input.charAt(i + 1))) { + if (input.charAt(i + 1) == '(') { + hasBracket = true; + } + caret_pos = i; + nCarets++; + } else if (nCarets > 0) { + if (hasBracket + && (i > 0) + && currentChar == ')' + && input.charAt(i - 1) != '\\') { + index = i + 1; + Superscript node = new Superscript(); + node.setLiteral(input.substring(caret_pos + 2, i)); + node.setLevel(level); + return node; + } else if (!hasBracket && Character.isWhitespace(currentChar)) { + index = i; + Superscript node = new Superscript(); + node.setLiteral(input.substring(caret_pos + 1, i)); + node.setLevel(level); + return node; + } else if (!hasBracket && (i == length - 1)) { + index = i + 1; + Superscript node = new Superscript(); + node.setLiteral(input.substring(caret_pos + 1, i + 1)); + node.setLevel(level); + return node; + } else if ((i + 1) < length + && (i > 0) + && currentChar == '^' + && input.charAt(i - 1) != '\\' + && !Character.isWhitespace(input.charAt(i + 1))) { + index = i; + Superscript node = new Superscript(); + node.setLiteral(input.substring(caret_pos + 1, i)); + node.setLevel(level); + node.setLevel(level); + return node; + } + } + } + return null; + } +} + diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptPlugin.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptPlugin.java new file mode 100644 index 00000000..7e220bb3 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptPlugin.java @@ -0,0 +1,38 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import androidx.annotation.NonNull; + +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.MarkwonVisitor; +import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; + +public class SuperscriptPlugin extends AbstractMarkwonPlugin { + + SuperscriptPlugin() { + + } + + public static SuperscriptPlugin create() { + return new SuperscriptPlugin(); + } + + @Override + public void configure(@NonNull Registry registry) { + registry.require(MarkwonInlineParserPlugin.class, plugin -> + plugin.factoryBuilder().addInlineProcessor(new SuperscriptParser())); + } + + @Override + public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { + builder.on(Superscript.class, (visitor, superscript) -> { + if (superscript.getLevel() < 29) { // Arbitrary nesting limit + final int start = visitor.length(); + visitor.builder().append(superscript.getLiteral()); + visitor.visitChildren(superscript); + visitor.setSpans(start, new SuperScriptSpan()); + } else { + visitor.clear(); + } + }); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java index 41bb5e98..f005f5c8 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java @@ -87,53 +87,9 @@ public final class Utils { regexed = REGEX_PATTERN[7].matcher(regexed).replaceAll("$0"); regexed = REGEX_PATTERN[8].matcher(regexed).replaceAll("$0"); - //return fixSuperScript(regexed); - // We don't want to fix super scripts here because we need the original markdown later for editing posts return regexed; } - public static String fixSuperScript(String regexedMarkdown) { - StringBuilder regexed = new StringBuilder(regexedMarkdown); - boolean hasBracket = false; - int nCarets = 0; - for (int i = 0; i < regexed.length(); i++) { - char currentChar = regexed.charAt(i); - if (currentChar == '^') { - if (!(i > 0 && regexed.charAt(i - 1) == '\\')) { - if (i < regexed.length() - 1 && regexed.charAt(i + 1) == '(') { - regexed.replace(i, i + 2, ""); - hasBracket = true; - } else { - regexed.replace(i, i + 1, ""); - } - nCarets++; - } - } else if (currentChar == ')' && hasBracket) { - hasBracket = false; - regexed.replace(i, i + 1, ""); - nCarets--; - } else if (currentChar == '\n') { - hasBracket = false; - for (int j = 0; j < nCarets; j++) { - regexed.insert(i, ""); - i += 6; - } - nCarets = 0; - } else if (currentChar == ' ' && !hasBracket) { - for (int j = 0; j < nCarets; j++) { - regexed.insert(i, ""); - i += 6; - } - nCarets = 0; - } - } - for (int j = 0; j < nCarets; j++) { - regexed.append(""); - } - - return regexed.toString(); - } - public static String parseInlineGifInComments(String markdown) { StringBuilder markdownStringBuilder = new StringBuilder(markdown); Pattern inlineGifPattern = REGEX_PATTERN[9];