diff --git a/app-sample/build.gradle b/app-sample/build.gradle
index 9e4f0f23..0ea4fa44 100644
--- a/app-sample/build.gradle
+++ b/app-sample/build.gradle
@@ -45,19 +45,46 @@ androidExtensions {
features = ["parcelize"]
}
+configurations.all {
+ exclude group: 'org.jetbrains', module: 'annotations-java5'
+}
+
dependencies {
kapt project(':sample-utils:processor')
+ deps['annotationProcessor'].with {
+ kapt it['prism4j-bundler']
+ }
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation project(':markwon-core')
+ implementation project(':markwon-editor')
+ implementation project(':markwon-ext-latex')
+ implementation project(':markwon-ext-strikethrough')
+ implementation project(':markwon-ext-tables')
+ implementation project(':markwon-ext-tasklist')
+ implementation project(':markwon-html')
+ implementation project(':markwon-image')
+ implementation project(':markwon-inline-parser')
+ implementation project(':markwon-linkify')
+ implementation project(':markwon-recycler')
+ implementation project(':markwon-recycler-table')
+ implementation project(':markwon-simple-ext')
+ implementation project(':markwon-syntax-highlight')
+
+ implementation project(':markwon-image-picasso')
+ implementation project(':markwon-image-glide')
deps.with {
implementation it['x-recycler-view']
implementation it['x-cardview']
implementation it['x-fragment']
+ implementation it['okhttp']
+ implementation it['prism4j']
implementation it['gson']
implementation it['adapt']
implementation it['debug']
+ implementation it['android-svg']
+ implementation it['android-gif']
}
}
diff --git a/app-sample/src/debug/res/layout/flowlayout_preview.xml b/app-sample/src/debug/res/layout/flowlayout_preview.xml
index 4f9f98a1..c78c9d10 100644
--- a/app-sample/src/debug/res/layout/flowlayout_preview.xml
+++ b/app-sample/src/debug/res/layout/flowlayout_preview.xml
@@ -13,7 +13,7 @@
android:layout_height="wrap_content"
android:text="Hey!" />
-
-
+
-
-
+
\ No newline at end of file
diff --git a/app-sample/src/main/AndroidManifest.xml b/app-sample/src/main/AndroidManifest.xml
index eed3ca3b..16c2d250 100644
--- a/app-sample/src/main/AndroidManifest.xml
+++ b/app-sample/src/main/AndroidManifest.xml
@@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools"
package="io.noties.markwon.app">
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/assets/README.md b/app-sample/src/main/assets/README.md
new file mode 120000
index 00000000..ff5c7960
--- /dev/null
+++ b/app-sample/src/main/assets/README.md
@@ -0,0 +1 @@
+../../../../README.md
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/App.kt b/app-sample/src/main/java/io/noties/markwon/app/App.kt
index 444ded43..41351f0c 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/App.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/App.kt
@@ -3,6 +3,8 @@ package io.noties.markwon.app
import android.app.Application
import io.noties.debug.AndroidLogDebugOutput
import io.noties.debug.Debug
+import io.noties.markwon.app.sample.SampleManager
+import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@Suppress("unused")
@@ -13,10 +15,12 @@ class App : Application() {
Debug.init(AndroidLogDebugOutput(BuildConfig.DEBUG))
- sampleManager = SampleManager(this, Executors.newCachedThreadPool())
+ executorService = Executors.newCachedThreadPool()
+ sampleManager = SampleManager(this, executorService)
}
companion object {
+ lateinit var executorService: ExecutorService
lateinit var sampleManager: SampleManager
}
}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/readme/GithubImageDestinationProcessor.kt b/app-sample/src/main/java/io/noties/markwon/app/readme/GithubImageDestinationProcessor.kt
new file mode 100644
index 00000000..f94f3a5d
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/readme/GithubImageDestinationProcessor.kt
@@ -0,0 +1,25 @@
+package io.noties.markwon.app.readme
+
+import android.net.Uri
+import android.text.TextUtils
+import io.noties.markwon.image.destination.ImageDestinationProcessor
+import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute
+
+class GithubImageDestinationProcessor(
+ username: String = "noties",
+ repository: String = "Markwon",
+ branch: String = "master"
+) : ImageDestinationProcessor() {
+
+ private val processor = ImageDestinationProcessorRelativeToAbsolute("https://github.com/$username/$repository/raw/$branch/")
+
+ override fun process(destination: String): String {
+ // process only images without scheme information
+ val uri = Uri.parse(destination)
+ return if (TextUtils.isEmpty(uri.scheme)) {
+ processor.process(destination)
+ } else {
+ destination
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeActivity.kt b/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeActivity.kt
new file mode 100644
index 00000000..870c2b29
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeActivity.kt
@@ -0,0 +1,166 @@
+package io.noties.markwon.app.readme
+
+import android.app.Activity
+import android.content.Context
+import android.net.Uri
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import androidx.recyclerview.widget.DefaultItemAnimator
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import io.noties.debug.Debug
+import io.noties.markwon.AbstractMarkwonPlugin
+import io.noties.markwon.Markwon
+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.tasklist.TaskListPlugin
+import io.noties.markwon.html.HtmlPlugin
+import io.noties.markwon.image.ImagesPlugin
+import io.noties.markwon.recycler.MarkwonAdapter
+import io.noties.markwon.recycler.SimpleEntry
+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.prism4j.Prism4j
+import io.noties.prism4j.annotations.PrismBundle
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import org.commonmark.ext.gfm.tables.TableBlock
+import org.commonmark.node.FencedCodeBlock
+import java.io.IOException
+
+@PrismBundle(includeAll = true)
+class ReadMeActivity : Activity() {
+
+ private lateinit var progressBar: View
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_read_me)
+
+ progressBar = findViewById(R.id.progress_bar)
+
+ val data = intent.data
+
+ Debug.i(data)
+
+ initAppBar(data)
+
+ initRecyclerView(data)
+ }
+
+ private val markwon: Markwon
+ get() = Markwon.builder(this)
+ .usePlugin(ImagesPlugin.create())
+ .usePlugin(HtmlPlugin.create())
+ .usePlugin(TableEntryPlugin.create(this))
+ .usePlugin(SyntaxHighlightPlugin.create(Prism4j(GrammarLocatorDef()), Prism4jThemeDefault.create(0)))
+ .usePlugin(TaskListPlugin.create(this))
+ .usePlugin(ReadMeImageDestinationPlugin(intent.data))
+ .usePlugin(object : AbstractMarkwonPlugin() {
+ override fun configureVisitor(builder: MarkwonVisitor.Builder) {
+ builder.on(FencedCodeBlock::class.java) { visitor, block ->
+ // we actually won't be applying code spans here, as our custom view will
+ // draw background and apply mono typeface
+ //
+ // NB the `trim` operation on literal (as code will have a new line at the end)
+ val code = visitor.configuration()
+ .syntaxHighlight()
+ .highlight(block.info, block.literal.trim())
+ visitor.builder().append(code)
+ }
+ }
+ })
+ .build()
+
+ private fun initAppBar(data: Uri?) {
+ val appBar = findViewById(R.id.app_bar)
+ appBar.findViewById(R.id.app_bar_icon).setOnClickListener { onBackPressed() }
+
+ val (title: String, subtitle: String?) = if (data == null) {
+ Pair("README.md", null)
+ } else {
+ Pair(data.lastPathSegment ?: "", data.toString())
+ }
+
+ appBar.findViewById(R.id.title).text = title
+ appBar.findViewById(R.id.subtitle).textOrHide(subtitle)
+ }
+
+ private fun initRecyclerView(data: Uri?) {
+
+ val adapter = MarkwonAdapter.builder(R.layout.adapter_node, R.id.text_view)
+ .include(FencedCodeBlock::class.java, SimpleEntry.create(R.layout.adapter_node_code_block, R.id.text_view))
+ .include(TableBlock::class.java, TableEntry.create {
+ it
+ .tableLayout(R.layout.adapter_node_table_block, R.id.table_layout)
+ .textLayoutIsRoot(R.layout.view_table_entry_cell)
+ })
+ .build()
+
+ val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
+ recyclerView.layoutManager = LinearLayoutManager(this)
+ recyclerView.setHasFixedSize(true)
+ recyclerView.itemAnimator = DefaultItemAnimator()
+ recyclerView.adapter = adapter
+
+ load(applicationContext, data) { result ->
+
+ when (result) {
+ is Result.Failure -> Debug.e(result.throwable)
+ is Result.Success -> {
+ val markwon = markwon
+ val node = markwon.parse(result.markdown)
+ if (window != null) {
+ recyclerView.post {
+ adapter.setParsedMarkdown(markwon, node)
+ adapter.notifyDataSetChanged()
+ progressBar.hidden = true
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private sealed class Result {
+ data class Success(val markdown: String) : Result()
+ data class Failure(val throwable: Throwable) : Result()
+ }
+
+ private companion object {
+ fun load(context: Context, data: Uri?, callback: (Result) -> Unit) = try {
+
+ if (data == null) {
+ callback.invoke(Result.Success(loadReadMe(context)))
+ } else {
+ val request = Request.Builder()
+ .get()
+ .url(ReadMeUtils.buildRawGithubUrl(data))
+ .build()
+ OkHttpClient().newCall(request).enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ callback.invoke(Result.Failure(e))
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ val md = response.body()?.string() ?: ""
+ callback.invoke(Result.Success(md))
+ }
+ })
+ }
+
+ } catch (t: Throwable) {
+ callback.invoke(Result.Failure(t))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeImageDestinationPlugin.kt b/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeImageDestinationPlugin.kt
new file mode 100644
index 00000000..a4d25210
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/readme/ReadMeImageDestinationPlugin.kt
@@ -0,0 +1,21 @@
+package io.noties.markwon.app.readme
+
+import android.net.Uri
+import io.noties.markwon.AbstractMarkwonPlugin
+import io.noties.markwon.MarkwonConfiguration
+import io.noties.markwon.app.utils.ReadMeUtils
+
+class ReadMeImageDestinationPlugin(private val data: Uri?) : AbstractMarkwonPlugin() {
+ override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
+ val info = ReadMeUtils.parseInfo(data)
+ if (info == null) {
+ builder.imageDestinationProcessor(GithubImageDestinationProcessor())
+ } else {
+ builder.imageDestinationProcessor(GithubImageDestinationProcessor(
+ username = info.username,
+ repository = info.repository,
+ branch = info.branch
+ ))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/MainActivity.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
similarity index 84%
rename from app-sample/src/main/java/io/noties/markwon/app/MainActivity.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
index f0fc8e35..e60c63d7 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/MainActivity.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
@@ -1,9 +1,9 @@
-package io.noties.markwon.app
+package io.noties.markwon.app.sample
import android.os.Bundle
import android.view.Window
import androidx.fragment.app.FragmentActivity
-import io.noties.markwon.app.ui.SampleListFragment
+import io.noties.markwon.app.sample.ui.SampleListFragment
class MainActivity : FragmentActivity() {
diff --git a/app-sample/src/main/java/io/noties/markwon/app/Sample.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/Sample.kt
similarity index 92%
rename from app-sample/src/main/java/io/noties/markwon/app/Sample.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/Sample.kt
index ffb7c5bd..9ba5cd02 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/Sample.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/Sample.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app
+package io.noties.markwon.app.sample
import android.os.Parcelable
import io.noties.markwon.sample.annotations.MarkwonArtifact
diff --git a/app-sample/src/main/java/io/noties/markwon/app/adapt/SampleItem.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleItem.kt
similarity index 97%
rename from app-sample/src/main/java/io/noties/markwon/app/adapt/SampleItem.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/SampleItem.kt
index c294b874..56576f11 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/adapt/SampleItem.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleItem.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.adapt
+package io.noties.markwon.app.sample
import android.text.Spanned
import android.view.LayoutInflater
@@ -8,8 +8,7 @@ import android.widget.TextView
import io.noties.adapt.Item
import io.noties.markwon.Markwon
import io.noties.markwon.app.R
-import io.noties.markwon.app.Sample
-import io.noties.markwon.app.base.FlowLayout
+import io.noties.markwon.app.widget.FlowLayout
import io.noties.markwon.app.utils.displayName
import io.noties.markwon.app.utils.hidden
import io.noties.markwon.app.utils.tagDisplayName
diff --git a/app-sample/src/main/java/io/noties/markwon/app/SampleManager.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
similarity index 98%
rename from app-sample/src/main/java/io/noties/markwon/app/SampleManager.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
index 7addbabb..b45fd616 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/SampleManager.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app
+package io.noties.markwon.app.sample
import android.content.Context
import io.noties.markwon.app.utils.Cancellable
diff --git a/app-sample/src/main/java/io/noties/markwon/app/SampleSearch.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleSearch.kt
similarity index 91%
rename from app-sample/src/main/java/io/noties/markwon/app/SampleSearch.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/SampleSearch.kt
index 6f79aef4..2cc7a26e 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/SampleSearch.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleSearch.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app
+package io.noties.markwon.app.sample
import io.noties.markwon.sample.annotations.MarkwonArtifact
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonSample.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonSample.kt
similarity index 89%
rename from app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonSample.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonSample.kt
index 67b78ccb..522acac1 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonSample.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonSample.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.ui
+package io.noties.markwon.app.sample.ui
import android.view.LayoutInflater
import android.view.View
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonTextViewSample.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonTextViewSample.kt
similarity index 92%
rename from app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonTextViewSample.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonTextViewSample.kt
index 58c4f5c8..64b767ec 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/MarkwonTextViewSample.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/MarkwonTextViewSample.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.ui
+package io.noties.markwon.app.sample.ui
import android.content.Context
import android.view.View
diff --git a/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleCodeFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleCodeFragment.kt
new file mode 100644
index 00000000..fe4d95a5
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleCodeFragment.kt
@@ -0,0 +1,74 @@
+package io.noties.markwon.app.sample.ui
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import io.noties.markwon.app.App
+import io.noties.markwon.app.R
+import io.noties.markwon.app.sample.Sample
+import io.noties.markwon.app.utils.hidden
+import io.noties.markwon.app.utils.readCode
+import io.noties.markwon.syntax.Prism4jSyntaxHighlight
+import io.noties.markwon.syntax.Prism4jThemeDefault
+import io.noties.prism4j.Prism4j
+import io.noties.prism4j.annotations.PrismBundle
+
+@PrismBundle(include = ["java", "kotlin"], grammarLocatorClassName = ".GrammarLocatorSourceCode")
+class SampleCodeFragment : Fragment() {
+
+ private lateinit var progressBar: View
+ private lateinit var textView: TextView
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.fragment_sample_code, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ progressBar = view.findViewById(R.id.progress_bar)
+ textView = view.findViewById(R.id.text_view)
+
+ load()
+ }
+
+ private fun load() {
+ App.executorService.submit {
+ val code = sample.readCode(requireContext())
+ val prism = Prism4j(GrammarLocatorSourceCode())
+ val highlight = Prism4jSyntaxHighlight.create(prism, Prism4jThemeDefault.create(0))
+ val language = when (code.language) {
+ Sample.Language.KOTLIN -> "kotlin"
+ Sample.Language.JAVA -> "java"
+ }
+ val text = highlight.highlight(language, code.sourceCode)
+
+ textView.post {
+ //attached
+ if (context != null) {
+ progressBar.hidden = true
+ textView.text = text
+ }
+ }
+ }
+ }
+
+ private val sample: Sample by lazy(LazyThreadSafetyMode.NONE) {
+ arguments!!.getParcelable(ARG_SAMPLE)
+ }
+
+ companion object {
+ private const val ARG_SAMPLE = "arg.Sample"
+
+ fun init(sample: Sample): SampleCodeFragment {
+ return SampleCodeFragment().apply {
+ arguments = Bundle().apply {
+ putParcelable(ARG_SAMPLE, sample)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleFragment.kt
similarity index 97%
rename from app-sample/src/main/java/io/noties/markwon/app/ui/SampleFragment.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleFragment.kt
index 59ca1533..f07f6de6 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleFragment.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleFragment.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.ui
+package io.noties.markwon.app.sample.ui
import android.os.Bundle
import android.view.LayoutInflater
@@ -8,7 +8,7 @@ import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import io.noties.markwon.app.R
-import io.noties.markwon.app.Sample
+import io.noties.markwon.app.sample.Sample
import io.noties.markwon.app.utils.active
class SampleFragment : Fragment() {
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleListFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
similarity index 97%
rename from app-sample/src/main/java/io/noties/markwon/app/ui/SampleListFragment.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
index 57f906ca..fc68b7c8 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleListFragment.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.ui
+package io.noties.markwon.app.sample.ui
import android.content.Context
import android.os.Bundle
@@ -19,11 +19,11 @@ import io.noties.debug.Debug
import io.noties.markwon.Markwon
import io.noties.markwon.app.App
import io.noties.markwon.app.R
-import io.noties.markwon.app.Sample
-import io.noties.markwon.app.SampleManager
-import io.noties.markwon.app.SampleSearch
-import io.noties.markwon.app.adapt.SampleItem
-import io.noties.markwon.app.base.SearchBar
+import io.noties.markwon.app.sample.Sample
+import io.noties.markwon.app.sample.SampleManager
+import io.noties.markwon.app.sample.SampleSearch
+import io.noties.markwon.app.sample.SampleItem
+import io.noties.markwon.app.widget.SearchBar
import io.noties.markwon.app.utils.Cancellable
import io.noties.markwon.app.utils.displayName
import io.noties.markwon.app.utils.onPreDraw
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/SamplePreviewFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SamplePreviewFragment.kt
similarity index 93%
rename from app-sample/src/main/java/io/noties/markwon/app/ui/SamplePreviewFragment.kt
rename to app-sample/src/main/java/io/noties/markwon/app/sample/ui/SamplePreviewFragment.kt
index 3bd64ce0..24e12c9f 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/SamplePreviewFragment.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SamplePreviewFragment.kt
@@ -1,11 +1,11 @@
-package io.noties.markwon.app.ui
+package io.noties.markwon.app.sample.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
-import io.noties.markwon.app.Sample
+import io.noties.markwon.app.sample.Sample
class SamplePreviewFragment : Fragment() {
diff --git a/app-sample/src/main/java/io/noties/markwon/app/samples/FirstSample.kt b/app-sample/src/main/java/io/noties/markwon/app/samples/FirstSample.kt
index cf20d3a5..cc4c512a 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/samples/FirstSample.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/samples/FirstSample.kt
@@ -1,7 +1,7 @@
package io.noties.markwon.app.samples
import io.noties.markwon.Markwon
-import io.noties.markwon.app.ui.MarkwonTextViewSample
+import io.noties.markwon.app.sample.ui.MarkwonTextViewSample
import io.noties.markwon.sample.annotations.MarkwonArtifact
import io.noties.markwon.sample.annotations.MarkwonSampleInfo
diff --git a/app-sample/src/main/java/io/noties/markwon/app/samples/nested/SecondSample.kt b/app-sample/src/main/java/io/noties/markwon/app/samples/nested/SecondSample.kt
index c63e645e..6707dfea 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/samples/nested/SecondSample.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/samples/nested/SecondSample.kt
@@ -1,7 +1,7 @@
package io.noties.markwon.app.samples.nested
import io.noties.markwon.Markwon
-import io.noties.markwon.app.ui.MarkwonTextViewSample
+import io.noties.markwon.app.sample.ui.MarkwonTextViewSample
import io.noties.markwon.sample.annotations.MarkwonArtifact
import io.noties.markwon.sample.annotations.MarkwonSampleInfo
diff --git a/app-sample/src/main/java/io/noties/markwon/app/samples/nested/ThirdSample.java b/app-sample/src/main/java/io/noties/markwon/app/samples/nested/ThirdSample.java
index 2e7ef678..032d3eb2 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/samples/nested/ThirdSample.java
+++ b/app-sample/src/main/java/io/noties/markwon/app/samples/nested/ThirdSample.java
@@ -1,7 +1,7 @@
package io.noties.markwon.app.samples.nested;
import io.noties.markwon.Markwon;
-import io.noties.markwon.app.ui.MarkwonTextViewSample;
+import io.noties.markwon.app.sample.ui.MarkwonTextViewSample;
import io.noties.markwon.sample.annotations.MarkwonArtifact;
import io.noties.markwon.sample.annotations.MarkwonSampleInfo;
diff --git a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleCodeFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/ui/SampleCodeFragment.kt
deleted file mode 100644
index e2de2050..00000000
--- a/app-sample/src/main/java/io/noties/markwon/app/ui/SampleCodeFragment.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package io.noties.markwon.app.ui
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import io.noties.markwon.app.R
-import io.noties.markwon.app.Sample
-import io.noties.markwon.app.utils.readCode
-
-class SampleCodeFragment : Fragment() {
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- return inflater.inflate(R.layout.fragment_sample_code, container, false)
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- val textView: TextView = view.findViewById(R.id.text_view)
- val code = sample.readCode(requireContext())
-
- textView.text = code.sourceCode
- }
-
- private val sample: Sample by lazy(LazyThreadSafetyMode.NONE) {
- arguments!!.getParcelable(ARG_SAMPLE)
- }
-
- companion object {
- private const val ARG_SAMPLE = "arg.Sample"
-
- fun init(sample: Sample): SampleCodeFragment {
- return SampleCodeFragment().apply {
- arguments = Bundle().apply {
- putParcelable(ARG_SAMPLE, sample)
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/utils/InputStreamUtils.kt b/app-sample/src/main/java/io/noties/markwon/app/utils/InputStreamUtils.kt
new file mode 100644
index 00000000..d146a4c1
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/utils/InputStreamUtils.kt
@@ -0,0 +1,21 @@
+package io.noties.markwon.app.utils
+
+import java.io.IOException
+import java.io.InputStream
+import java.util.Scanner
+
+fun InputStream.readStringAndClose(): String {
+ try {
+ val scanner = Scanner(this).useDelimiter("\\A")
+ if (scanner.hasNext()) {
+ return scanner.next()
+ }
+ return ""
+ } finally {
+ try {
+ close()
+ } catch (e: IOException) {
+ // ignored
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/utils/ReadMeUtils.kt b/app-sample/src/main/java/io/noties/markwon/app/utils/ReadMeUtils.kt
new file mode 100644
index 00000000..a6fbfebf
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/utils/ReadMeUtils.kt
@@ -0,0 +1,44 @@
+package io.noties.markwon.app.utils
+
+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+?)\\/(.+)")
+
+ data class GithubInfo(
+ val username: String,
+ val repository: String,
+ val branch: String,
+ val fileName: String
+ )
+
+ fun parseInfo(data: Uri?): GithubInfo? {
+
+ if (data == null) {
+ return null
+ }
+
+ val matcher = RE.matcher(data.toString())
+ if (!matcher.matches()) {
+ return null
+ }
+
+ return GithubInfo(
+ username = matcher.group(1),
+ repository = matcher.group(2),
+ branch = matcher.group(3),
+ fileName = matcher.group(4)
+ )
+ }
+
+ fun buildRawGithubUrl(data: Uri): String {
+ val info = parseInfo(data)
+ return if (info == null) {
+ data.toString()
+ } else {
+ "https://github.com/${info.username}/${info.repository}/raw/${info.branch}/${info.fileName}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtils.java b/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtils.java
index 2f4195e3..2f500f9b 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtils.java
+++ b/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtils.java
@@ -12,7 +12,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
-import io.noties.markwon.app.Sample;
+import io.noties.markwon.app.sample.Sample;
public abstract class SampleUtils {
diff --git a/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtilsKt.kt b/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtilsKt.kt
index 6e88689c..dfbd8d27 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtilsKt.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/utils/SampleUtilsKt.kt
@@ -1,10 +1,9 @@
package io.noties.markwon.app.utils
import android.content.Context
-import io.noties.markwon.app.Sample
+import io.noties.markwon.app.sample.Sample
import io.noties.markwon.sample.annotations.MarkwonArtifact
import java.io.InputStream
-import java.util.Scanner
val MarkwonArtifact.displayName: String
get() = "@${artifactName()}"
@@ -22,11 +21,6 @@ fun Sample.readCode(context: Context): Sample.Code {
.removePrefix(SAMPLE_PREFIX)
.replace('.', '/')
- // now, we have 2 possibilities -> Kotlin or Java
- fun read(stream: InputStream): String {
- return Scanner(stream).useDelimiter("\\A").next()
- }
-
fun obtain(path: String): InputStream? {
return try {
assets.open(path)
@@ -35,6 +29,7 @@ fun Sample.readCode(context: Context): Sample.Code {
}
}
+ // now, we have 2 possibilities -> Kotlin or Java
var language: Sample.Language = Sample.Language.KOTLIN
var stream = obtain("$path.kt")
if (stream == null) {
@@ -46,13 +41,12 @@ fun Sample.readCode(context: Context): Sample.Code {
throw IllegalStateException("Cannot obtain sample file at path: $path")
}
- val code = read(stream)
-
- try {
- stream.close()
- } catch (t: Throwable) {
- // ignore
- }
+ val code = stream.readStringAndClose()
return Sample.Code(language, code)
+}
+
+fun loadReadMe(context: Context): String {
+ val stream = context.assets.open("README.md")
+ return stream.readStringAndClose()
}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/utils/TextViewUtils.kt b/app-sample/src/main/java/io/noties/markwon/app/utils/TextViewUtils.kt
new file mode 100644
index 00000000..8ff0660a
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/utils/TextViewUtils.kt
@@ -0,0 +1,9 @@
+package io.noties.markwon.app.utils
+
+import android.text.TextUtils
+import android.widget.TextView
+
+fun TextView.textOrHide(text: CharSequence?) {
+ this.text = text
+ this.hidden = TextUtils.isEmpty(text)
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/base/FlowLayout.kt b/app-sample/src/main/java/io/noties/markwon/app/widget/FlowLayout.kt
similarity index 99%
rename from app-sample/src/main/java/io/noties/markwon/app/base/FlowLayout.kt
rename to app-sample/src/main/java/io/noties/markwon/app/widget/FlowLayout.kt
index be8fca71..a975f453 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/base/FlowLayout.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/widget/FlowLayout.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.base
+package io.noties.markwon.app.widget
import android.content.Context
import android.util.AttributeSet
diff --git a/app-sample/src/main/java/io/noties/markwon/app/base/SearchBar.kt b/app-sample/src/main/java/io/noties/markwon/app/widget/SearchBar.kt
similarity index 98%
rename from app-sample/src/main/java/io/noties/markwon/app/base/SearchBar.kt
rename to app-sample/src/main/java/io/noties/markwon/app/widget/SearchBar.kt
index ba4f644d..5c7508a1 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/base/SearchBar.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/widget/SearchBar.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.base
+package io.noties.markwon.app.widget
import android.content.Context
import android.util.AttributeSet
diff --git a/app-sample/src/main/java/io/noties/markwon/app/base/TextField.kt b/app-sample/src/main/java/io/noties/markwon/app/widget/TextField.kt
similarity index 95%
rename from app-sample/src/main/java/io/noties/markwon/app/base/TextField.kt
rename to app-sample/src/main/java/io/noties/markwon/app/widget/TextField.kt
index 0e826282..c6c627a8 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/base/TextField.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/widget/TextField.kt
@@ -1,4 +1,4 @@
-package io.noties.markwon.app.base
+package io.noties.markwon.app.widget
import android.content.Context
import android.util.AttributeSet
diff --git a/app-sample/src/main/res/layout/activity_read_me.xml b/app-sample/src/main/res/layout/activity_read_me.xml
new file mode 100644
index 00000000..bb37ae71
--- /dev/null
+++ b/app-sample/src/main/res/layout/activity_read_me.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/layout/adapt_sample.xml b/app-sample/src/main/res/layout/adapt_sample.xml
index 2885673d..4b0d1b0c 100644
--- a/app-sample/src/main/res/layout/adapt_sample.xml
+++ b/app-sample/src/main/res/layout/adapt_sample.xml
@@ -54,7 +54,7 @@
android:textAppearance="?android:attr/textAppearance"
tools:text="Description goes here" />
-
-
+
-
-
+
diff --git a/app-sample/src/main/res/layout/adapter_node.xml b/app-sample/src/main/res/layout/adapter_node.xml
new file mode 100644
index 00000000..7ddaf140
--- /dev/null
+++ b/app-sample/src/main/res/layout/adapter_node.xml
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/layout/adapter_node_code_block.xml b/app-sample/src/main/res/layout/adapter_node_code_block.xml
new file mode 100644
index 00000000..894e3835
--- /dev/null
+++ b/app-sample/src/main/res/layout/adapter_node_code_block.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/layout/adapter_node_table_block.xml b/app-sample/src/main/res/layout/adapter_node_table_block.xml
new file mode 100644
index 00000000..aaaaa369
--- /dev/null
+++ b/app-sample/src/main/res/layout/adapter_node_table_block.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/layout/fragment_sample_code.xml b/app-sample/src/main/res/layout/fragment_sample_code.xml
index d8ac6205..bdd14090 100644
--- a/app-sample/src/main/res/layout/fragment_sample_code.xml
+++ b/app-sample/src/main/res/layout/fragment_sample_code.xml
@@ -1,28 +1,41 @@
-
-
+ android:layout_height="match_parent">
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/layout/fragment_sample_list.xml b/app-sample/src/main/res/layout/fragment_sample_list.xml
index 353095ce..18dacbac 100644
--- a/app-sample/src/main/res/layout/fragment_sample_list.xml
+++ b/app-sample/src/main/res/layout/fragment_sample_list.xml
@@ -42,7 +42,7 @@
android:paddingBottom="36dip"
tools:layout_marginTop="56dip" />
-
-
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/values/dimens.xml b/app-sample/src/main/res/values/dimens.xml
index 21ba14f5..1707aa4b 100644
--- a/app-sample/src/main/res/values/dimens.xml
+++ b/app-sample/src/main/res/values/dimens.xml
@@ -11,4 +11,7 @@
1dip
56dip
+
+ 64dip
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/values/strings.xml b/app-sample/src/main/res/values/strings.xml
index 2ed0d912..4567d309 100644
--- a/app-sample/src/main/res/values/strings.xml
+++ b/app-sample/src/main/res/values/strings.xml
@@ -4,4 +4,5 @@
Preview
Code
+
\ No newline at end of file
diff --git a/sample/build.gradle b/sample/build.gradle
index b87cab5e..81d14d9e 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -60,6 +60,7 @@ dependencies {
implementation it['debug']
implementation it['adapt']
implementation it['android-svg']
+ implementation it['android-gif']
}
deps['annotationProcessor'].with {