diff options
author | Docile-Alligator <chineseperson5@gmail.com> | 2021-12-09 13:24:46 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-09 13:24:46 +0000 |
commit | 35cbd2431899221d35fc449f34c4e7e5a78e4213 (patch) | |
tree | 5f673811c3d1d470ac6e164b00cd261d9b2e1e43 /app | |
parent | e8e434056279915cce8c20b63031b28673b7ef03 (diff) | |
parent | 97fc6d2873246426fa935acb498590d7f0e27a21 (diff) | |
download | infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar.gz infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar.bz2 infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar.lz infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar.xz infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.tar.zst infinity-for-reddit-35cbd2431899221d35fc449f34c4e7e5a78e4213.zip |
Merge pull request #575 from scria1000/markdown-enhancements
Markdown enhancements
Diffstat (limited to '')
22 files changed, 360 insertions, 206 deletions
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..a9275779 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,9 @@ 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.SpoilerParserPlugin; +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; @@ -135,6 +135,8 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA private Uri capturedImageUri; private ArrayList<UploadedImage> uploadedImages = new ArrayList<>(); private Menu mMenu; + private int commentColor; + private int commentSpoilerBackgroundColor; @Override protected void onCreate(Bundle savedInstanceState) { @@ -166,18 +168,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 @@ -195,6 +195,7 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA builder.linkColor(linkColor); } }) + .usePlugin(SpoilerParserPlugin.create(commentColor, commentSpoilerBackgroundColor)) .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) .build(); if (parentTextMarkdown != null) { @@ -220,18 +221,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 @@ -342,7 +341,9 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA protected void applyCustomTheme() { coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor()); applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, null, toolbar); - commentParentMarkwonView.setTextColor(mCustomThemeWrapper.getCommentColor()); + commentColor = mCustomThemeWrapper.getCommentColor(); + commentSpoilerBackgroundColor = commentColor | 0xFF000000; + commentParentMarkwonView.setTextColor(commentColor); divider.setBackgroundColor(mCustomThemeWrapper.getDividerColor()); commentEditText.setTextColor(mCustomThemeWrapper.getCommentColor()); int secondaryTextColor = mCustomThemeWrapper.getSecondaryTextColor(); 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<Comment int commentSpoilerBackgroundColor = mCommentColor | 0xFF000000; mMarkwon = Markwon.builder(mActivity) .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/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<RecyclerVi int linkColor = customThemeWrapper.getLinkColor(); mCommentMarkwon = Markwon.builder(mActivity) .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/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<Message, RecyclerView.ViewHolder> { @@ -108,18 +98,16 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter<Message, Recycl mMarkwon = Markwon.builder(mContext) .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/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<Recycler int linkColor = customThemeWrapper.getLinkColor(); mPostDetailMarkwon = Markwon.builder(mActivity) .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/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<RecyclerView.ViewHolder> { @@ -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<RulesRecyclerViewAdapter.RuleViewHolder> { private Markwon markwon; @@ -47,18 +45,16 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecycler public RulesRecyclerViewAdapter(AppCompatActivity activity, CustomThemeWrapper customThemeWrapper) { 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/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/SpoilerOpening.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java new file mode 100644 index 00000000..279cba65 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpening.java @@ -0,0 +1,21 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import org.commonmark.node.CustomNode; +import org.commonmark.node.Visitor; + +class SpoilerOpening extends CustomNode { + private String literal; + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + public String getLiteral() { + return literal; + } + + public void setLiteral(String literal) { + this.literal = literal; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java new file mode 100644 index 00000000..391e4a88 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerOpeningParser.java @@ -0,0 +1,27 @@ +package ml.docilealligator.infinityforreddit.markdown; + +import androidx.annotation.Nullable; + +import org.commonmark.node.Node; + +import io.noties.markwon.inlineparser.InlineProcessor; + +public class SpoilerOpeningParser extends InlineProcessor { + @Override + public char specialCharacter() { + return '>'; + } + + @Nullable + @Override + protected Node parse() { + index++; + if (peek() == '!') { + index++; + SpoilerOpening node = new SpoilerOpening(); + node.setLiteral(">!"); + return node; + } + return null; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java index 3a05b71c..85dc2be5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SpoilerParserPlugin.java @@ -11,7 +11,6 @@ import androidx.annotation.NonNull; import org.commonmark.node.Block; import org.commonmark.node.BlockQuote; import org.commonmark.node.HtmlBlock; -import org.commonmark.node.HtmlInline; import org.commonmark.parser.Parser; import java.util.ArrayList; @@ -19,13 +18,17 @@ import java.util.Set; import java.util.Stack; import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.MarkwonVisitor; import io.noties.markwon.core.CorePlugin; import io.noties.markwon.core.spans.CodeBlockSpan; import io.noties.markwon.core.spans.CodeSpan; +import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin; public class SpoilerParserPlugin extends AbstractMarkwonPlugin { private final int textColor; private final int backgroundColor; + private boolean textHasSpoiler = false; + private int firstSpoilerStart = -1; SpoilerParserPlugin(int textColor, int backgroundColor) { this.textColor = textColor; @@ -37,12 +40,29 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin { } @Override + public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { + builder.on(SpoilerOpening.class, (visitor, opening) -> { + textHasSpoiler = true; + if (firstSpoilerStart == -1) { + firstSpoilerStart = visitor.length(); + } + visitor.builder().append(opening.getLiteral()); + }); + } + + @Override + public void configure(@NonNull Registry registry) { + registry.require(MarkwonInlineParserPlugin.class, plugin -> + plugin.factoryBuilder().addInlineProcessor(new SpoilerOpeningParser()) + ); + } + + @Override public void configureParser(@NonNull Parser.Builder builder) { builder.customBlockParserFactory(new BlockQuoteWithExceptionParser.Factory()); Set<Class<? extends Block>> blocks = CorePlugin.enabledBlockTypes(); blocks.remove(HtmlBlock.class); - blocks.remove(HtmlInline.class); blocks.remove(BlockQuote.class); builder.enabledBlockTypes(blocks); @@ -50,16 +70,19 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin { @Override public void afterSetText(@NonNull TextView textView) { - textView.setHighlightColor(Color.TRANSPARENT); - - if (textView.getText().length() < 5) { + if (!textHasSpoiler || textView.getText().length() < 5) { + firstSpoilerStart = 0; return; } + textView.setHighlightColor(Color.TRANSPARENT); + SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText()); - ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder); + ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder, firstSpoilerStart); + firstSpoilerStart = 0; if (spoilers.size() == 0) { + textHasSpoiler = false; return; } @@ -118,31 +141,32 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin { // Don't allow more than one new line after every non-blank line // Try not to care about recursing spoilers, we just want the outermost spoiler because // spoiler revealing-hiding breaks with recursing spoilers - private ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown) { + private ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown, int start) { final int MAX_NEW_LINE = 1; int length = markdown.length(); Stack<Integer> openSpoilerStack = new Stack<>(); ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>(); int new_lines = 0; - for (int i = 0; i < length; i++) { - if (markdown.charAt(i) == '\n') { + for (int i = start; i < length; i++) { + char currentChar = markdown.charAt(i); + if (currentChar == '\n') { new_lines++; if (new_lines > MAX_NEW_LINE) { openSpoilerStack.clear(); new_lines = 0; } - } else if ((markdown.charAt(i) != '>') - && (markdown.charAt(i) != '<') - && (markdown.charAt(i) != '!')) { + } else if ((currentChar != '>') + && (currentChar != '<') + && (currentChar != '!')) { new_lines = 0; } else if ((i + 1 < length) - && markdown.charAt(i) == '>' + && currentChar == '>' && markdown.charAt(i + 1) == '!') { openSpoilerStack.push(i + 2); } else if ((i + 1 < length) && (i - 1 >= 0) && openSpoilerStack.size() > 0 && markdown.charAt(i - 1) != '>' - && markdown.charAt(i) == '!' + && currentChar == '!' && markdown.charAt(i + 1) == '<') { var pos = openSpoilerStack.pop(); if (!closedSpoilers.isEmpty() 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("</?sup>", 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..10c6dcfd --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/SuperscriptParser.java @@ -0,0 +1,116 @@ +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); + 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 2da97f97..3f08b372 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, "<sup>"); - hasBracket = true; - } else { - regexed.replace(i, i + 1, "<sup>"); - } - nCarets++; - } - } else if (currentChar == ')' && hasBracket) { - hasBracket = false; - regexed.replace(i, i + 1, "</sup>"); - nCarets--; - } else if (currentChar == '\n') { - hasBracket = false; - for (int j = 0; j < nCarets; j++) { - regexed.insert(i, "</sup>"); - i += 6; - } - nCarets = 0; - } else if (currentChar == ' ' && !hasBracket) { - for (int j = 0; j < nCarets; j++) { - regexed.insert(i, "</sup>"); - i += 6; - } - nCarets = 0; - } - } - for (int j = 0; j < nCarets; j++) { - regexed.append("</sup>"); - } - - return regexed.toString(); - } - public static String parseInlineGifInComments(String markdown) { StringBuilder markdownStringBuilder = new StringBuilder(markdown); Pattern inlineGifPattern = REGEX_PATTERN[9]; |