mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2024-12-22 08:40:03 +02:00
Markdown support
This commit is contained in:
parent
6790158ed9
commit
e954fd860a
6 changed files with 92 additions and 31 deletions
|
@ -85,6 +85,8 @@ android {
|
|||
}
|
||||
}
|
||||
configurations {
|
||||
cleanedAnnotations
|
||||
implementation.exclude group: 'org.jetbrains', module: 'annotations'
|
||||
all {
|
||||
exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx'
|
||||
}
|
||||
|
@ -186,6 +188,9 @@ dependencies {
|
|||
|
||||
|
||||
implementation 'io.noties.markwon:core:4.6.2'
|
||||
implementation 'io.noties.markwon:ext-tables:4.6.2'
|
||||
implementation 'io.noties.markwon:syntax-highlight:4.6.2'
|
||||
annotationProcessor 'io.noties:prism4j-bundler:2.0.0'
|
||||
|
||||
//************ CAST **************///
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ import java.util.Objects;
|
|||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||
import app.fedilab.android.peertube.services.GlobalUploadObserver;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import io.noties.prism4j.annotations.PrismBundle;
|
||||
|
||||
@PrismBundle(includeAll = true, grammarLocatorClassName = ".MySuperGrammerLocator")
|
||||
|
||||
public class MainApplication extends MultiDexApplication {
|
||||
|
||||
|
|
|
@ -37,5 +37,15 @@ public class MarkdownConverter {
|
|||
public String code;
|
||||
public int position;
|
||||
public URLSpan urlSpan;
|
||||
|
||||
public int regexPosition(List<MarkdownItem> markdownItems) {
|
||||
int position = 0;
|
||||
for (MarkdownItem markdownItem : markdownItems) {
|
||||
if (markdownItem.code.equals(code) && position <= this.position) {
|
||||
position++;
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import android.view.View;
|
|||
import android.webkit.URLUtil;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
@ -71,6 +72,7 @@ import java.util.regex.Pattern;
|
|||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.MySuperGrammerLocator;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
import app.fedilab.android.databinding.PopupLinksBinding;
|
||||
|
@ -89,6 +91,10 @@ import app.fedilab.android.mastodon.ui.drawer.StatusAdapter;
|
|||
import app.fedilab.android.mastodon.viewmodel.mastodon.FiltersVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import io.noties.markwon.Markwon;
|
||||
import io.noties.markwon.ext.tables.TablePlugin;
|
||||
import io.noties.markwon.syntax.Prism4jThemeDefault;
|
||||
import io.noties.markwon.syntax.SyntaxHighlightPlugin;
|
||||
import io.noties.prism4j.Prism4j;
|
||||
|
||||
public class SpannableHelper {
|
||||
|
||||
|
@ -149,44 +155,56 @@ public class SpannableHelper {
|
|||
} else {
|
||||
initialContent = new SpannableString(text);
|
||||
}
|
||||
|
||||
boolean markdownSupport = sharedpreferences.getBoolean(context.getString(R.string.SET_MARKDOWN_SUPPORT), true);
|
||||
//Get all links
|
||||
MarkdownConverter markdownConverter = new MarkdownConverter();
|
||||
markdownConverter.markdownItems = new ArrayList<>();
|
||||
int next;
|
||||
int position = 0;
|
||||
for (int i = 0; i < initialContent.length(); i = next) {
|
||||
// find the next span transition
|
||||
next = initialContent.nextSpanTransition(i, initialContent.length(), URLSpan.class);
|
||||
MarkdownConverter.MarkdownItem markdownItem = new MarkdownConverter.MarkdownItem();
|
||||
markdownItem.code = initialContent.subSequence(i, next).toString();
|
||||
SpannableStringBuilder content;
|
||||
if (markdownSupport) {
|
||||
MarkdownConverter markdownConverter = new MarkdownConverter();
|
||||
markdownConverter.markdownItems = new ArrayList<>();
|
||||
int next;
|
||||
int position = 0;
|
||||
for (int i = 0; i < initialContent.length(); i = next) {
|
||||
// find the next span transition
|
||||
next = initialContent.nextSpanTransition(i, initialContent.length(), URLSpan.class);
|
||||
MarkdownConverter.MarkdownItem markdownItem = new MarkdownConverter.MarkdownItem();
|
||||
markdownItem.code = initialContent.subSequence(i, next).toString();
|
||||
|
||||
markdownItem.position = position;
|
||||
// get all spans in this range
|
||||
URLSpan[] spans = initialContent.getSpans(i, next, URLSpan.class);
|
||||
if (spans != null && spans.length > 0) {
|
||||
markdownItem.urlSpan = spans[0];
|
||||
markdownItem.position = position;
|
||||
// get all spans in this range
|
||||
URLSpan[] spans = initialContent.getSpans(i, next, URLSpan.class);
|
||||
if (spans != null && spans.length > 0) {
|
||||
markdownItem.urlSpan = spans[0];
|
||||
}
|
||||
|
||||
if (markdownItem.code.trim().length() > 0) {
|
||||
markdownConverter.markdownItems.add(markdownItem);
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
if (markdownItem.code.trim().length() > 0) {
|
||||
markdownConverter.markdownItems.add(markdownItem);
|
||||
final Markwon markwon = Markwon.builder(context)
|
||||
.usePlugin(TablePlugin.create(context))
|
||||
.usePlugin(SyntaxHighlightPlugin.create(new Prism4j(new MySuperGrammerLocator()), Prism4jThemeDefault.create())).build();
|
||||
|
||||
final Spanned markdown = markwon.toMarkdown(initialContent.toString());
|
||||
content = new SpannableStringBuilder(markdown);
|
||||
position = 0;
|
||||
for (MarkdownConverter.MarkdownItem markdownItem : markdownConverter.markdownItems) {
|
||||
Pattern p = Pattern.compile("(" + Pattern.quote(markdownItem.code) + ")", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(content);
|
||||
int fetchPosition = 1;
|
||||
while (m.find()) {
|
||||
int regexPosition = markdownItem.regexPosition(markdownConverter.markdownItems);
|
||||
if (regexPosition == fetchPosition) {
|
||||
content.setSpan(markdownItem.urlSpan, m.start(), m.end(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
fetchPosition++;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
} else {
|
||||
content = new SpannableStringBuilder(initialContent);
|
||||
}
|
||||
final Markwon markwon = Markwon.create(context);
|
||||
|
||||
final Spanned markdown = markwon.toMarkdown(initialContent.toString());
|
||||
SpannableStringBuilder content = new SpannableStringBuilder(markdown);
|
||||
position = 0;
|
||||
for (MarkdownConverter.MarkdownItem markdownItem : markdownConverter.markdownItems) {
|
||||
Pattern p = Pattern.compile("(" + Pattern.quote(markdownItem.code) + ")", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(content);
|
||||
while (m.find()) {
|
||||
content.setSpan(markdownItem.urlSpan, m.start(), m.end(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
|
||||
URLSpan[] urls = content.getSpans(0, (content.length() - 1), URLSpan.class);
|
||||
//Loop through links
|
||||
|
@ -336,6 +354,23 @@ public class SpannableHelper {
|
|||
return trimSpannable(new SpannableStringBuilder(content));
|
||||
}
|
||||
|
||||
public interface Prism4jTheme {
|
||||
|
||||
@ColorInt
|
||||
int background();
|
||||
|
||||
@ColorInt
|
||||
int textColor();
|
||||
|
||||
void apply(
|
||||
@NonNull String language,
|
||||
@NonNull Prism4j.Syntax syntax,
|
||||
@NonNull SpannableStringBuilder builder,
|
||||
int start,
|
||||
int end
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static void makeLinks(Context context, SpannableStringBuilder content, String url, int start, int end) {
|
||||
String newUrl = url;
|
||||
|
|
|
@ -1156,6 +1156,7 @@
|
|||
|
||||
<string name="SET_GROUP_REBLOGS" translatable="false">SET_GROUP_REBLOGS</string>
|
||||
<string name="SET_BOOST_ORIGINAL_DATE" translatable="false">SET_BOOST_ORIGINAL_DATE</string>
|
||||
<string name="SET_MARKDOWN_SUPPORT" translatable="false">SET_MARKDOWN_SUPPORT</string>
|
||||
<string name="SET_TRUNCATE_LINKS" translatable="false">SET_TRUNCATE_LINKS</string>
|
||||
<string name="SET_TRUNCATE_LINKS_MAX" translatable="false">SET_TRUNCATE_LINKS_MAX</string>
|
||||
|
||||
|
@ -1907,6 +1908,7 @@
|
|||
<string name="also_followed_by">Followed by:</string>
|
||||
<string name="Directory">Directory</string>
|
||||
<string name="boost_original_date">Display original date for boosts</string>
|
||||
<string name="markdown_support">Markdown support</string>
|
||||
<string name="set_disable_release_notes">Disable release notes</string>
|
||||
<string name="set_disable_release_notes_indication">When a new version is published, you will not be alerted inside the app.</string>
|
||||
<string name="formula">Formula</string>
|
||||
|
|
|
@ -50,6 +50,13 @@
|
|||
app:singleLineTitle="false"
|
||||
app:title="@string/boost_original_date" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="@string/SET_MARKDOWN_SUPPORT"
|
||||
app:singleLineTitle="false"
|
||||
app:title="@string/markdown_support" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
app:iconSpaceReserved="false"
|
||||
|
|
Loading…
Reference in a new issue