Sample app process outgoing repositories links

This commit is contained in:
Dimitry Ivanov 2020-06-26 17:51:59 +03:00
parent 186390805a
commit 1a90f1e609
7 changed files with 83 additions and 5 deletions

View File

@ -85,6 +85,6 @@ dependencies {
implementation it['adapt']
implementation it['debug']
implementation it['android-svg']
implementation it['android-gif']
implementation it['android-gif-impl']
}
}

View File

@ -35,9 +35,13 @@
<data
android:host="github.com"
android:pathPattern=".*\\.md"
android:scheme="https" />
<data android:pathPattern=".*\\.md" />
<data android:pathPattern=".*\\..*\\.md" />
<data android:pathPattern=".*\\..*\\..*\\.md"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\.md"/>
</intent-filter>
</activity>

View File

@ -1,8 +1,14 @@
package io.noties.markwon.app
import android.app.Application
import android.content.ComponentName
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.os.Build
import io.noties.debug.AndroidLogDebugOutput
import io.noties.debug.Debug
import io.noties.markwon.app.readme.ReadMeActivity
import io.noties.markwon.app.sample.SampleManager
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@ -17,6 +23,31 @@ class App : Application() {
executorService = Executors.newCachedThreadPool()
sampleManager = SampleManager(this, executorService)
ensureReadmeShortcut()
}
private fun ensureReadmeShortcut() {
if (Build.VERSION.SDK_INT < 25) {
return
}
val manager = getSystemService(ShortcutManager::class.java) ?: return
@Suppress("ReplaceNegatedIsEmptyWithIsNotEmpty")
if (!manager.dynamicShortcuts.isEmpty()) {
return
}
val intent = Intent(Intent.ACTION_VIEW).apply {
component = ComponentName(this@App, ReadMeActivity::class.java)
}
val shortcut = ShortcutInfo.Builder(this, "readme")
.setShortLabel("README")
.setIntent(intent)
.build()
manager.addDynamicShortcuts(mutableListOf(shortcut))
}
companion object {

View File

@ -12,12 +12,14 @@ import androidx.recyclerview.widget.RecyclerView
import io.noties.debug.Debug
import io.noties.markwon.AbstractMarkwonPlugin
import io.noties.markwon.Markwon
import io.noties.markwon.MarkwonConfiguration
import io.noties.markwon.MarkwonVisitor
import io.noties.markwon.app.R
import io.noties.markwon.app.utils.ReadMeUtils
import io.noties.markwon.app.utils.hidden
import io.noties.markwon.app.utils.loadReadMe
import io.noties.markwon.app.utils.textOrHide
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin
import io.noties.markwon.ext.tasklist.TaskListPlugin
import io.noties.markwon.html.HtmlPlugin
import io.noties.markwon.image.ImagesPlugin
@ -27,6 +29,7 @@ import io.noties.markwon.recycler.table.TableEntry
import io.noties.markwon.recycler.table.TableEntryPlugin
import io.noties.markwon.syntax.Prism4jThemeDefault
import io.noties.markwon.syntax.SyntaxHighlightPlugin
import io.noties.markwon.utils.DumpNodes
import io.noties.prism4j.Prism4j
import io.noties.prism4j.annotations.PrismBundle
import okhttp3.Call
@ -65,6 +68,7 @@ class ReadMeActivity : Activity() {
.usePlugin(TableEntryPlugin.create(this))
.usePlugin(SyntaxHighlightPlugin.create(Prism4j(GrammarLocatorDef()), Prism4jThemeDefault.create(0)))
.usePlugin(TaskListPlugin.create(this))
.usePlugin(StrikethroughPlugin.create())
.usePlugin(ReadMeImageDestinationPlugin(intent.data))
.usePlugin(object : AbstractMarkwonPlugin() {
override fun configureVisitor(builder: MarkwonVisitor.Builder) {
@ -79,6 +83,10 @@ class ReadMeActivity : Activity() {
visitor.builder().append(code)
}
}
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
builder.linkResolver(ReadMeLinkResolver())
}
})
.build()
@ -120,6 +128,7 @@ class ReadMeActivity : Activity() {
is Result.Success -> {
val markwon = markwon
val node = markwon.parse(result.markdown)
Debug.i(DumpNodes.dump(node))
if (window != null) {
recyclerView.post {
adapter.setParsedMarkdown(markwon, node)

View File

@ -0,0 +1,18 @@
package io.noties.markwon.app.readme
import android.view.View
import io.noties.markwon.LinkResolverDef
import io.noties.markwon.app.utils.ReadMeUtils
class ReadMeLinkResolver : LinkResolverDef() {
override fun resolve(view: View, link: String) {
val matcher = ReadMeUtils.RE_REPOSITORY.matcher(link)
val url = if (matcher.matches()) {
ReadMeUtils.buildRepositoryReadMeUrl(matcher.group(1), matcher.group(2))
} else {
link
}
super.resolve(view, url)
}
}

View File

@ -4,8 +4,13 @@ import android.net.Uri
import java.util.regex.Pattern
object ReadMeUtils {
// username, repo, branch, lastPathSegment
private val RE = Pattern.compile("^https:\\/\\/github\\.com\\/(\\w+?)\\/(\\w+?)\\/(?:blob|raw)\\/(\\w+?)\\/(.+)")
@Suppress("RegExpRedundantEscape")
private val RE_FILE = Pattern.compile("^https:\\/\\/github\\.com\\/([\\w-.]+?)\\/([\\w-.]+?)\\/(?:blob|raw)\\/([\\w-.]+?)\\/(.+)\$")
@Suppress("RegExpRedundantEscape")
val RE_REPOSITORY: Pattern = Pattern.compile("^https:\\/\\/github.com\\/([\\w-.]+?)\\/([\\w-.]+?)\\/*\$")
data class GithubInfo(
val username: String,
@ -20,7 +25,7 @@ object ReadMeUtils {
return null
}
val matcher = RE.matcher(data.toString())
val matcher = RE_FILE.matcher(data.toString())
if (!matcher.matches()) {
return null
}
@ -38,7 +43,16 @@ object ReadMeUtils {
return if (info == null) {
data.toString()
} else {
"https://github.com/${info.username}/${info.repository}/raw/${info.branch}/${info.fileName}"
buildRawGithubUrl(info)
}
}
@Suppress("MemberVisibilityCanBePrivate")
fun buildRawGithubUrl(info: GithubInfo): String {
return "https://github.com/${info.username}/${info.repository}/raw/${info.branch}/${info.fileName}"
}
fun buildRepositoryReadMeUrl(username: String, repository: String): String {
return buildRawGithubUrl(GithubInfo(username, repository, "master", "README.md"))
}
}

View File

@ -76,7 +76,9 @@ ext {
'commonmark-strikethrough': "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:$commonMarkVersion",
'commonmark-table' : "com.atlassian.commonmark:commonmark-ext-gfm-tables:$commonMarkVersion",
'android-svg' : 'com.caverock:androidsvg:1.4',
// we need 2 gif artifacts at long as we have a difference in version used for API compatibility
'android-gif' : 'pl.droidsonroids.gif:android-gif-drawable:1.2.15',
'android-gif-impl' : 'pl.droidsonroids.gif:android-gif-drawable:1.2.20',
'jlatexmath-android' : 'ru.noties:jlatexmath-android:0.2.0',
'okhttp' : 'com.squareup.okhttp3:okhttp:3.9.0',
'prism4j' : 'io.noties:prism4j:2.0.0',