diff --git a/app-sample/build.gradle b/app-sample/build.gradle
new file mode 100644
index 00000000..a63d63f0
--- /dev/null
+++ b/app-sample/build.gradle
@@ -0,0 +1,50 @@
+apply plugin: 'com.android.application'
+
+android {
+
+ compileSdkVersion config['compile-sdk']
+ buildToolsVersion config['build-tools']
+
+ defaultConfig {
+ applicationId 'io.noties.markwon.app'
+ minSdkVersion 23
+ targetSdkVersion config['target-sdk']
+ versionCode 1
+ versionName version
+
+ resConfig 'en'
+
+ javaCompileOptions {
+ annotationProcessorOptions {
+ arguments = [
+ // cannot cast GString...
+ // cannot use `-`
+ 'markwon.samples.file': "\"${projectDir}/samples.json\"".toString()
+ ]
+ }
+ }
+ }
+
+ dexOptions {
+ preDexLibraries true
+ javaMaxHeapSize '5g'
+ }
+
+ compileOptions {
+ targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_1_8
+ }
+
+ sourceSets {
+ main {
+ java.srcDirs += '../sample-utils/annotations'
+ }
+ }
+
+
+}
+
+dependencies {
+ implementation 'io.noties:debug:5.1.0'
+ annotationProcessor project(':sample-utils:processor')
+}
diff --git a/app-sample/src/main/AndroidManifest.xml b/app-sample/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..eed3ca3b
--- /dev/null
+++ b/app-sample/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/App.java b/app-sample/src/main/java/io/noties/markwon/app/App.java
new file mode 100644
index 00000000..22d93c21
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/App.java
@@ -0,0 +1,16 @@
+package io.noties.markwon.app;
+
+import android.app.Application;
+
+import io.noties.debug.AndroidLogDebugOutput;
+import io.noties.debug.Debug;
+
+public class App extends Application {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ Debug.init(new AndroidLogDebugOutput(true));
+ }
+}
diff --git a/app-sample/src/main/java/io/noties/markwon/app/MainActivity.java b/app-sample/src/main/java/io/noties/markwon/app/MainActivity.java
new file mode 100644
index 00000000..301fe240
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/MainActivity.java
@@ -0,0 +1,16 @@
+package io.noties.markwon.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+
+ }
+}
diff --git a/app-sample/src/main/java/io/noties/markwon/app/Test.java b/app-sample/src/main/java/io/noties/markwon/app/Test.java
new file mode 100644
index 00000000..d9c61e70
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/Test.java
@@ -0,0 +1,15 @@
+package io.noties.markwon.app;
+
+import io.noties.markwon.sample.annotations.MarkwonArtifact;
+import io.noties.markwon.sample.annotations.MarkwonSample;
+
+@MarkwonSample(
+ id = "202006163161416",
+ title = "The first sample title",
+ description = "This is description",
+ artifacts = {MarkwonArtifact.CORE, MarkwonArtifact.EDITOR},
+ tags = "none"
+)
+public class Test {
+
+}
diff --git a/app-sample/src/main/res/drawable/ic_launcher_background.xml b/app-sample/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..49c86ecb
--- /dev/null
+++ b/app-sample/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..c4a603d4
--- /dev/null
+++ b/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..c4a603d4
--- /dev/null
+++ b/app-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/mipmap-hdpi/ic_launcher.png b/app-sample/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..fdd31819
Binary files /dev/null and b/app-sample/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app-sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app-sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..c787da34
Binary files /dev/null and b/app-sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/app-sample/src/main/res/mipmap-mdpi/ic_launcher.png b/app-sample/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..597bbed4
Binary files /dev/null and b/app-sample/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app-sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app-sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..b80592da
Binary files /dev/null and b/app-sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/app-sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/app-sample/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..c11d8df7
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app-sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app-sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..d36bf1df
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..2e240579
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..d1f1abf9
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..5d9f00fc
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..37333547
Binary files /dev/null and b/app-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/app-sample/src/main/res/values/colors.xml b/app-sample/src/main/res/values/colors.xml
new file mode 100644
index 00000000..d9cb06d5
--- /dev/null
+++ b/app-sample/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #5CB85C
+
\ 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
new file mode 100644
index 00000000..74a01aa0
--- /dev/null
+++ b/app-sample/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Markwon
+
\ No newline at end of file
diff --git a/app-sample/src/main/res/values/styles.xml b/app-sample/src/main/res/values/styles.xml
new file mode 100644
index 00000000..955c5cc3
--- /dev/null
+++ b/app-sample/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/art/sample-app.epgz b/art/sample-app.epgz
index 90c74c7c..f3f37831 100644
Binary files a/art/sample-app.epgz and b/art/sample-app.epgz differ
diff --git a/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonArtifact.java b/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonArtifact.java
new file mode 100644
index 00000000..d9abd329
--- /dev/null
+++ b/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonArtifact.java
@@ -0,0 +1,21 @@
+package io.noties.markwon.sample.annotations;
+
+public enum MarkwonArtifact {
+ CORE,
+ EDITOR,
+ EXT_LATEX,
+ EXT_STRIKETHROUGH,
+ EXT_TABLES,
+ EXT_TASKLIST,
+ HTML,
+ IMAGE,
+ IMAGE_COIL,
+ IMAGE_GLIDE,
+ IMAGE_PICASSO,
+ INLINE_PARSER,
+ LINKIFY,
+ RECYCLER,
+ RECYCLER_TABLE,
+ SIMPLE_EXT,
+ SYNTAX_HIGHLIGHT
+}
diff --git a/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonSample.java b/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonSample.java
new file mode 100644
index 00000000..dd825c38
--- /dev/null
+++ b/sample-utils/annotations/io/noties/markwon/sample/annotations/MarkwonSample.java
@@ -0,0 +1,30 @@
+package io.noties.markwon.sample.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface MarkwonSample {
+ /**
+ * Actual format is not important, but this key must be set in order to persist sample.
+ * This key should not change during lifetime of sample
+ *
+ * {@code id} date in `YYYYMMDDHHmmss` format (UTC),
+ * a simple live template can be used:
+ * {@code
+ * groovyScript("new Date().format('YYYYMMDDHHmmss', TimeZone.getTimeZone('UTC'))")
+ * }
+ */
+ String id();
+
+ String title();
+
+ String description();
+
+ MarkwonArtifact[] artifacts();
+
+ String[] tags();
+}
diff --git a/sample-utils/processor/build.gradle b/sample-utils/processor/build.gradle
new file mode 100644
index 00000000..4c8e775a
--- /dev/null
+++ b/sample-utils/processor/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'java-library'
+
+sourceCompatibility = JavaVersion.VERSION_1_8
+targetCompatibility = JavaVersion.VERSION_1_8
+
+sourceSets {
+ main.java.srcDirs += '../annotations'
+}
+
+dependencies {
+ implementation deps['x-annotations']
+}
\ No newline at end of file
diff --git a/sample-utils/processor/src/main/java/io/noties/markwon/sample/processor/MarkwonSampleProcessor.java b/sample-utils/processor/src/main/java/io/noties/markwon/sample/processor/MarkwonSampleProcessor.java
new file mode 100644
index 00000000..7ca997b3
--- /dev/null
+++ b/sample-utils/processor/src/main/java/io/noties/markwon/sample/processor/MarkwonSampleProcessor.java
@@ -0,0 +1,65 @@
+package io.noties.markwon.sample.processor;
+
+import androidx.annotation.NonNull;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+import io.noties.markwon.sample.annotations.MarkwonSample;
+
+public class MarkwonSampleProcessor extends AbstractProcessor {
+
+ private static final String KEY_SAMPLES_FILE = "markwon.samples.file";
+
+ private Messager messager;
+ private String samplesFilePath;
+
+ @Override
+ public Set getSupportedOptions() {
+ return Collections.singleton(KEY_SAMPLES_FILE);
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public Set getSupportedAnnotationTypes() {
+ return Collections.singleton(MarkwonSample.class.getName());
+ }
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnvironment) {
+ super.init(processingEnvironment);
+
+ messager = processingEnvironment.getMessager();
+ samplesFilePath = processingEnvironment.getOptions().get(KEY_SAMPLES_FILE);
+ }
+
+ @Override
+ public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
+ if (!roundEnvironment.processingOver()) {
+ final Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(MarkwonSample.class);
+ if (elements != null) {
+ for (Element element : elements) {
+ process(element);
+ }
+ }
+ }
+ return false;
+ }
+
+ private void process(@NonNull Element element) {
+ messager.printMessage(Diagnostic.Kind.WARNING, samplesFilePath, element);
+ }
+}
diff --git a/sample-utils/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/sample-utils/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 00000000..c5b7c964
--- /dev/null
+++ b/sample-utils/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+io.noties.markwon.sample.processor.MarkwonSampleProcessor
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 8bf10dcb..d276c4ed 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -18,3 +18,6 @@ include ':app', ':sample',
':markwon-simple-ext',
':markwon-syntax-highlight',
':markwon-test-span'
+
+include ':app-sample'
+include ':sample-utils:processor'