Эх сурвалжийг харах

Merge pull request #4692 from nextcloud/markdownPreview

Markdown rendering
Tobias Kaminsky 5 жил өмнө
parent
commit
954c76b11b

+ 9 - 0
build.gradle

@@ -57,6 +57,7 @@ configurations {
 ext {
     jacocoVersion = "0.8.2"
     daggerVersion = "2.24"
+    markwonVersion =  '4.1.2'
     androidLibraryVersion = "master-SNAPSHOT"
 
     travisBuild = System.getenv("TRAVIS") == "true"
@@ -317,6 +318,14 @@ dependencies {
     ktlint "com.pinterest:ktlint:0.35.0"
     implementation 'org.conscrypt:conscrypt-android:2.2.1'
 
+    // dependencies for markdown rendering
+    implementation ("io.noties.markwon:core:$markwonVersion")
+    implementation ("io.noties.markwon:ext-latex:$markwonVersion")
+    implementation ("io.noties.markwon:ext-strikethrough:$markwonVersion")
+    implementation ("io.noties.markwon:ext-tables:$markwonVersion")
+    implementation ("io.noties.markwon:ext-tasklist:$markwonVersion")
+    implementation ("io.noties.markwon:html:$markwonVersion")
+    implementation ("io.noties.markwon:linkify:$markwonVersion")
 
     // dependencies for local unit tests
     testImplementation 'junit:junit:4.12'

+ 1 - 1
src/main/AndroidManifest.xml

@@ -72,7 +72,7 @@
     must request the FOREGROUND_SERVICE permission -->
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
-    <uses-sdk tools:overrideLibrary="com.blikoon.qrcodescanner" />
+    <uses-sdk tools:overrideLibrary="com.blikoon.qrcodescanner, io.noties.markwon.ext.latex, io.noties.markwon.ext.strikethrough, io.noties.markwon.ext.tables, io.noties.markwon.ext.tasklist, io.noties.markwon.html, io.noties.markwon.linkify, io.noties.markwon.syntax, io.noties.markwon, ru.noties.jlatexmath.android" />
 
     <!-- Some Chromebooks don't support touch. Although not essential,
          it's a good idea to explicitly include this declaration. -->

+ 30 - 4
src/main/java/com/owncloud/android/ui/preview/PreviewTextFragment.java

@@ -20,10 +20,12 @@
 package com.owncloud.android.ui.preview;
 
 import android.accounts.Account;
+import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.Html;
+import android.text.Spanned;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -66,6 +68,11 @@ import javax.inject.Inject;
 import androidx.annotation.NonNull;
 import androidx.appcompat.widget.SearchView;
 import androidx.core.view.MenuItemCompat;
+import io.noties.markwon.Markwon;
+import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
+import io.noties.markwon.ext.tables.TablePlugin;
+import io.noties.markwon.ext.tasklist.TaskListPlugin;
+import io.noties.markwon.html.HtmlPlugin;
 
 public class PreviewTextFragment extends FileFragment implements SearchView.OnQueryTextListener, Injectable {
     private static final String EXTRA_FILE = "FILE";
@@ -120,8 +127,6 @@ public class PreviewTextFragment extends FileFragment implements SearchView.OnQu
         View ret = inflater.inflate(R.layout.text_file_preview, container, false);
         mTextPreview = ret.findViewById(R.id.text_preview);
 
-        mTextPreview = ret.findViewById(R.id.text_preview);
-
         mMultiView = ret.findViewById(R.id.multi_view);
 
         setupMultiView(ret);
@@ -243,7 +248,7 @@ public class PreviewTextFragment extends FileFragment implements SearchView.OnQu
                         mTextPreview.setText(Html.fromHtml(coloredText.replace("\n", "<br \\>")));
                     }
                 } else {
-                    mTextPreview.setText(mOriginalText);
+                    setText(mTextPreview, mOriginalText, getFile());
                 }
             }, delay);
         }
@@ -253,6 +258,17 @@ public class PreviewTextFragment extends FileFragment implements SearchView.OnQu
         }
     }
 
+    private Spanned getRenderedMarkdownText(Context context, String markdown) {
+        final Markwon markwon = Markwon.builder(context)
+            .usePlugin(TablePlugin.create(context))
+            .usePlugin(TaskListPlugin.create(context))
+            .usePlugin(StrikethroughPlugin.create())
+            .usePlugin(HtmlPlugin.create())
+            .build();
+
+        return markwon.toMarkdown(markdown);
+    }
+
     /**
      * Reads the file to preview and shows its contents. Too critical to be anonymous.
      */
@@ -324,7 +340,8 @@ public class PreviewTextFragment extends FileFragment implements SearchView.OnQu
             if (textView != null) {
                 mOriginalText = stringWriter.toString();
                 mSearchView.setOnQueryTextListener(PreviewTextFragment.this);
-                textView.setText(mOriginalText);
+
+                setText(textView, mOriginalText, getFile());
 
                 if (mSearchOpen) {
                     mSearchView.setQuery(mSearchQuery, true);
@@ -505,4 +522,13 @@ public class PreviewTextFragment extends FileFragment implements SearchView.OnQu
             }
         });
     }
+
+    private void setText(TextView textView, String text, OCFile file) {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN
+            && MimeTypeUtil.MIMETYPE_TEXT_MARKDOWN.equals(file.getMimeType())) {
+            textView.setText(getRenderedMarkdownText(getContext(), text));
+        } else {
+            textView.setText(text);
+        }
+    }
 }

+ 6 - 5
src/main/java/com/owncloud/android/utils/MimeTypeUtil.java

@@ -72,6 +72,7 @@ public final class MimeTypeUtil {
     private static final Map<String, Integer> MAIN_MIMETYPE_TO_ICON_MAPPING = new HashMap<>();
     /** Mapping: mime type for file extension. */
     private static final Map<String, List<String>> FILE_EXTENSION_TO_MIMETYPE_MAPPING = new HashMap<>();
+    public static final String MIMETYPE_TEXT_MARKDOWN = "text/markdown";
 
     static {
         populateFileExtensionMimeTypeMapping();
@@ -648,12 +649,12 @@ public final class MimeTypeUtil {
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("m4a", Collections.singletonList("audio/mp4"));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("m4b", Collections.singletonList("audio/m4b"));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("m4v", Collections.singletonList("video/mp4"));
-        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("markdown", Collections.singletonList("text/markdown"));
-        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mdown", Collections.singletonList("text/markdown"));
-        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("md", Collections.singletonList("text/markdown"));
+        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("markdown", Collections.singletonList(MIMETYPE_TEXT_MARKDOWN));
+        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mdown", Collections.singletonList(MIMETYPE_TEXT_MARKDOWN));
+        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("md", Collections.singletonList(MIMETYPE_TEXT_MARKDOWN));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mdb", Collections.singletonList("application/msaccess"));
-        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mdwn", Collections.singletonList("text/markdown"));
-        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mkd", Collections.singletonList("text/markdown"));
+        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mdwn", Collections.singletonList(MIMETYPE_TEXT_MARKDOWN));
+        FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mkd", Collections.singletonList(MIMETYPE_TEXT_MARKDOWN));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mef", Collections.singletonList("image/x-dcraw"));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mkv", Collections.singletonList("video/x-matroska"));
         FILE_EXTENSION_TO_MIMETYPE_MAPPING.put("mobi", Collections.singletonList("application/x-mobipocket-ebook"));