diff --git a/README.md b/README.md index 3b8e363b..012331f5 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,11 @@ [![Maven Central](https://img.shields.io/maven-central/v/com.halilibo.compose-richtext/richtext-ui.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.halilibo.compose-richtext%22) [![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0) -A collection of Compose libraries for working with rich text formatting and documents. This repo -is currently very experimental and really just proofs-of-concept: there are no tests and some things +A collection of Compose libraries for working with rich text formatting and documents. + +`richtext-ui`, `richtext-commonmark`, and `richtext-material-ui` are Kotlin Multiplatform Compose Libraries. + +This repo is currently very experimental and really just proofs-of-concept: there are no tests and some things might be broken or very non-performant. ---- diff --git a/android-sample/build.gradle.kts b/android-sample/build.gradle.kts new file mode 100644 index 00000000..f80c2f92 --- /dev/null +++ b/android-sample/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("com.android.application") + kotlin("android") +} + +android { + compileSdk = AndroidConfiguration.compileSdk + + defaultConfig { + minSdk = 21 + targetSdk = AndroidConfiguration.targetSdk + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = Compose.version + } + + lint { + disable("ComposableModifierFactory", "ModifierFactoryExtensionFunction", "ModifierFactoryReturnType", "ModifierFactoryUnreferencedReceiver") + } +} + +configurations.all { + resolutionStrategy.eachDependency { + if (requested.group.contains("org.jetbrains.compose")) { + val groupName = requested.group.replace("org.jetbrains.compose", "androidx.compose") + useTarget( + mapOf("group" to groupName, "name" to requested.name, "version" to Compose.version) + ) + } + } +} + +dependencies { + implementation(project(":printing")) + implementation(project(":richtext-commonmark")) + implementation(project(":richtext-ui-material")) + implementation(project(":slideshow")) + implementation(AndroidX.appcompat) + implementation(Compose.activity) + implementation(Compose.foundation) + implementation(Compose.icons) + implementation(Compose.material) + implementation(Compose.tooling) +} diff --git a/richtext-commonmark/proguard-rules.pro b/android-sample/proguard-rules.pro similarity index 100% rename from richtext-commonmark/proguard-rules.pro rename to android-sample/proguard-rules.pro diff --git a/sample/src/main/AndroidManifest.xml b/android-sample/src/main/AndroidManifest.xml similarity index 100% rename from sample/src/main/AndroidManifest.xml rename to android-sample/src/main/AndroidManifest.xml diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt similarity index 83% rename from sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt index 6f4bf705..a74c4572 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/Demo.kt @@ -14,18 +14,18 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.zachklipp.richtext.ui.BlockQuote -import com.zachklipp.richtext.ui.CodeBlock -import com.zachklipp.richtext.ui.FormattedList -import com.zachklipp.richtext.ui.Heading -import com.zachklipp.richtext.ui.HorizontalRule -import com.zachklipp.richtext.ui.ListType -import com.zachklipp.richtext.ui.ListType.Ordered -import com.zachklipp.richtext.ui.ListType.Unordered -import com.zachklipp.richtext.ui.RichTextScope -import com.zachklipp.richtext.ui.RichTextStyle -import com.zachklipp.richtext.ui.Table -import com.zachklipp.richtext.ui.material.MaterialRichText +import com.halilibo.richtext.ui.BlockQuote +import com.halilibo.richtext.ui.CodeBlock +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.Heading +import com.halilibo.richtext.ui.HorizontalRule +import com.halilibo.richtext.ui.ListType +import com.halilibo.richtext.ui.ListType.Ordered +import com.halilibo.richtext.ui.ListType.Unordered +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.RichTextStyle +import com.halilibo.richtext.ui.Table +import com.halilibo.richtext.ui.material.MaterialRichText @Preview(widthDp = 300, heightDp = 1000) @Composable fun RichTextDemoOnWhite() { diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt similarity index 99% rename from sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt index 80a570a2..4131d436 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/DocumentSample.kt @@ -52,9 +52,9 @@ import androidx.compose.ui.unit.constrainWidth import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.offset import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.FormattedList -import com.zachklipp.richtext.ui.ListType.Unordered -import com.zachklipp.richtext.ui.material.MaterialRichText +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.ListType.Unordered +import com.halilibo.richtext.ui.material.MaterialRichText import com.zachklipp.richtext.ui.printing.Printable import com.zachklipp.richtext.ui.printing.PrintableController import com.zachklipp.richtext.ui.printing.hideWhenPrinting diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt similarity index 97% rename from sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt index 55de803d..e7a724ba 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/MarkdownSample.kt @@ -25,10 +25,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.zachklipp.richtext.markdown.Markdown -import com.zachklipp.richtext.ui.RichTextStyle -import com.zachklipp.richtext.ui.material.MaterialRichText -import com.zachklipp.richtext.ui.resolveDefaults +import com.halilibo.richtext.markdown.Markdown +import com.halilibo.richtext.ui.RichTextStyle +import com.halilibo.richtext.ui.material.MaterialRichText +import com.halilibo.richtext.ui.resolveDefaults @Preview @Composable private fun MarkdownSamplePreview() { diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/PagedSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/PagedSample.kt similarity index 100% rename from sample/src/main/java/com/zachklipp/richtext/sample/PagedSample.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/PagedSample.kt diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt similarity index 97% rename from sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt index 8b9a21eb..302c6025 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/RichTextSample.kt @@ -25,8 +25,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.RichTextStyle -import com.zachklipp.richtext.ui.resolveDefaults +import com.halilibo.richtext.ui.RichTextStyle +import com.halilibo.richtext.ui.resolveDefaults @Preview @Composable private fun RichTextSamplePreview() { diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/SampleActivity.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/SampleActivity.kt similarity index 100% rename from sample/src/main/java/com/zachklipp/richtext/sample/SampleActivity.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/SampleActivity.kt diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt similarity index 95% rename from sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt index 37dd513f..52e69396 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/SampleLauncher.kt @@ -45,11 +45,12 @@ private val Samples = listOf Unit>>( var currentSampleIndex: Int? by remember { mutableStateOf(null) } Crossfade(currentSampleIndex) { index -> - index?.let { + if (index != null) { BackHandler(onBack = { currentSampleIndex = null }) - Samples[it].second() + Samples[index].second() + } else { + SamplesListScreen(onSampleClicked = { currentSampleIndex = it }) } - ?: SamplesListScreen(onSampleClicked = { currentSampleIndex = it }) } } diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/ScreenPreview.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/ScreenPreview.kt similarity index 100% rename from sample/src/main/java/com/zachklipp/richtext/sample/ScreenPreview.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/ScreenPreview.kt diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt similarity index 97% rename from sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt index 061ffeb4..7d4d4722 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/SlideshowSample.kt @@ -20,9 +20,9 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview -import com.zachklipp.richtext.ui.FormattedList -import com.zachklipp.richtext.ui.ListType.Ordered -import com.zachklipp.richtext.ui.material.MaterialRichText +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.ListType.Ordered +import com.halilibo.richtext.ui.material.MaterialRichText import com.zachklipp.richtext.ui.slideshow.BodySlide import com.zachklipp.richtext.ui.slideshow.NavigableContentContainer import com.zachklipp.richtext.ui.slideshow.SlideDivider diff --git a/sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt b/android-sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt similarity index 86% rename from sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt rename to android-sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt index 09365bcf..99c19cfa 100644 --- a/sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt +++ b/android-sample/src/main/java/com/zachklipp/richtext/sample/TextDemo.kt @@ -33,21 +33,21 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.material.MaterialRichText -import com.zachklipp.richtext.ui.string.InlineContent -import com.zachklipp.richtext.ui.string.RichTextString.Builder -import com.zachklipp.richtext.ui.string.RichTextString.Format -import com.zachklipp.richtext.ui.string.RichTextString.Format.Bold -import com.zachklipp.richtext.ui.string.RichTextString.Format.Code -import com.zachklipp.richtext.ui.string.RichTextString.Format.Italic -import com.zachklipp.richtext.ui.string.RichTextString.Format.Link -import com.zachklipp.richtext.ui.string.RichTextString.Format.Strikethrough -import com.zachklipp.richtext.ui.string.RichTextString.Format.Subscript -import com.zachklipp.richtext.ui.string.RichTextString.Format.Superscript -import com.zachklipp.richtext.ui.string.RichTextString.Format.Underline -import com.zachklipp.richtext.ui.string.Text -import com.zachklipp.richtext.ui.string.richTextString -import com.zachklipp.richtext.ui.string.withFormat +import com.halilibo.richtext.ui.material.MaterialRichText +import com.halilibo.richtext.ui.string.InlineContent +import com.halilibo.richtext.ui.string.RichTextString.Builder +import com.halilibo.richtext.ui.string.RichTextString.Format +import com.halilibo.richtext.ui.string.RichTextString.Format.Bold +import com.halilibo.richtext.ui.string.RichTextString.Format.Code +import com.halilibo.richtext.ui.string.RichTextString.Format.Italic +import com.halilibo.richtext.ui.string.RichTextString.Format.Link +import com.halilibo.richtext.ui.string.RichTextString.Format.Strikethrough +import com.halilibo.richtext.ui.string.RichTextString.Format.Subscript +import com.halilibo.richtext.ui.string.RichTextString.Format.Superscript +import com.halilibo.richtext.ui.string.RichTextString.Format.Underline +import com.halilibo.richtext.ui.string.Text +import com.halilibo.richtext.ui.string.richTextString +import com.halilibo.richtext.ui.string.withFormat import kotlinx.coroutines.delay import kotlinx.coroutines.launch diff --git a/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from sample/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to android-sample/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/sample/src/main/res/drawable/ic_launcher_background.xml b/android-sample/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from sample/src/main/res/drawable/ic_launcher_background.xml rename to android-sample/src/main/res/drawable/ic_launcher_background.xml diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to android-sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/android-sample/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from sample/src/main/res/mipmap-hdpi/ic_launcher.png rename to android-sample/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from sample/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to android-sample/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/android-sample/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from sample/src/main/res/mipmap-mdpi/ic_launcher.png rename to android-sample/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from sample/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to android-sample/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/android-sample/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from sample/src/main/res/mipmap-xhdpi/ic_launcher.png rename to android-sample/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to android-sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from sample/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to android-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to android-sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to android-sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/sample/src/main/res/values/colors.xml b/android-sample/src/main/res/values/colors.xml similarity index 100% rename from sample/src/main/res/values/colors.xml rename to android-sample/src/main/res/values/colors.xml diff --git a/sample/src/main/res/values/strings.xml b/android-sample/src/main/res/values/strings.xml similarity index 100% rename from sample/src/main/res/values/strings.xml rename to android-sample/src/main/res/values/strings.xml diff --git a/sample/src/main/res/values/styles.xml b/android-sample/src/main/res/values/styles.xml similarity index 100% rename from sample/src/main/res/values/styles.xml rename to android-sample/src/main/res/values/styles.xml diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 721c45a6..00000000 --- a/build.gradle +++ /dev/null @@ -1,196 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - ext.versions = [ - targetSdk: 30, - compose: '1.0.1', - kotlin: '1.5.21', - commonmark: '0.18.0' - ] - - rootProject.ext.defaultAndroidConfig = { - compileSdkVersion versions.targetSdk - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - defaultConfig { - minSdkVersion 21 - targetSdkVersion versions.targetSdk - versionCode 1 - versionName "1.0" - } - - buildFeatures { - compose = true - } - - composeOptions { - kotlinCompilerExtensionVersion versions.compose - } - - lintOptions { - disable "ComposableModifierFactory", "ModifierFactoryExtensionFunction", "ModifierFactoryReturnType", "ModifierFactoryUnreferencedReceiver" - } - } - - ext.deps = [ - android_gradle_plugin: "com.android.tools.build:gradle:7.0.0", - - androidx: [ - activity: "androidx.activity:activity:1.1.0", - annotations: "androidx.annotation:annotation:1.1.0", - appcompat: "androidx.appcompat:appcompat:1.3.0", - constraint_layout: "androidx.constraintlayout:constraintlayout:1.1.3", - fragment: "androidx.fragment:fragment:1.2.2", - // Note that we're not using the actual androidx material dep yet, it's still alpha. - material: "com.google.android.material:material:1.1.0", - recyclerview: "androidx.recyclerview:recyclerview:1.1.0", - // Note that we are *not* using lifecycle-viewmodel-savedstate, which at this - // writing is still in beta and still fixing bad bugs. Probably we'll never bother to, - // it doesn't really add value for us. - savedstate: "androidx.savedstate:savedstate:1.0.0", - transition: "androidx.transition:transition:1.3.1", - viewbinding: "androidx.databinding:viewbinding:3.6.1", - ], - compose: [ - activity: "androidx.activity:activity-compose:1.3.0", - foundation: "androidx.compose.foundation:foundation:${versions.compose}", - layout: "androidx.compose.foundation:foundation-layout:${versions.compose}", - material: "androidx.compose.material:material:${versions.compose}", - icons: "androidx.compose.material:material-icons-extended:${versions.compose}", - test: "androidx.ui:ui-test:${versions.compose}", - tooling: "androidx.compose.ui:ui-tooling:${versions.compose}", - tooling_preview: "androidx.compose.ui:ui-tooling-preview:${versions.compose}", - tooling_data: "androidx.compose.ui:ui-tooling-data:${versions.compose}", - ], - kotlin: [ - binaryCompatibilityValidatorPlugin: "org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0", - gradlePlugin: "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}", - stdlib: "org.jetbrains.kotlin:kotlin-stdlib-jdk8", - reflect: "org.jetbrains.kotlin:kotlin-reflect:${versions.kotlin}", - test: [ - common: "org.jetbrains.kotlin:kotlin-test-common", - annotations: "org.jetbrains.kotlin:kotlin-test-annotations-common", - jdk: "org.jetbrains.kotlin:kotlin-test-junit", - mockito: "com.nhaarman:mockito-kotlin-kt1.1:1.6.0" - ] - ], - commonmark: [ - core: "org.commonmark:commonmark:${versions.commonmark}", - tables: "org.commonmark:commonmark-ext-gfm-tables:${versions.commonmark}", - strikethrough: "org.commonmark:commonmark-ext-gfm-strikethrough:${versions.commonmark}" - ], - coil: "io.coil-kt:coil-compose:1.3.1", - mavenPublish: "com.vanniktech:gradle-maven-publish-plugin:0.17.0", - ktlint: "org.jlleitschuh.gradle:ktlint-gradle:10.0.0", - ] - - repositories { - mavenCentral() - gradlePluginPortal() - google() - } - - dependencies { - classpath deps.android_gradle_plugin - classpath deps.kotlin.binaryCompatibilityValidatorPlugin - classpath deps.kotlin.gradlePlugin - classpath deps.ktlint - classpath deps.mavenPublish - } -} - -plugins { - id('org.jetbrains.dokka') version '1.5.0' -} - -repositories { - mavenCentral() -} - -tasks.withType(org.jetbrains.dokka.gradle.DokkaMultiModuleTask).configureEach { - outputDirectory = rootProject.file('docs/api') - failOnWarning = true -} - -// See https://stackoverflow.com/questions/25324880/detect-ide-environment-with-gradle -def isRunningFromIde() { - return project.properties["android.injected.invoked.from.ide"] == "true" -} - -allprojects { - plugins.withId("com.vanniktech.maven.publish") { - mavenPublish { - sonatypeHost = "S01" - } - } -} - -subprojects { - repositories { - google() - mavenCentral() - } - - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - jvmTarget = "1.8" - - // Allow warnings when running from IDE, makes it easier to experiment. - if (!isRunningFromIde()) { - allWarningsAsErrors = true - } - - freeCompilerArgs = [ - "-Xopt-in=kotlin.RequiresOptIn", - ] - - // Require explicit public modifiers and types. - // TODO this should be moved to a top-level `kotlin { explicitApi() }` once that's working - // for android projects, see https://youtrack.jetbrains.com/issue/KT-37652. - // Tests aren't part of the public API, don't turn explicit API mode on for them. - - if (project.name != "sample" && !name.contains("test")) { - freeCompilerArgs += "-Xexplicit-api=strict" - } - } - } - - // taken from https://github.com/google/accompanist/blob/main/build.gradle - afterEvaluate { - if (tasks.findByName('dokkaHtmlPartial') == null) { - // If dokka isn't enabled on this module, skip - return - } - - tasks.named('dokkaHtmlPartial') { - dokkaSourceSets.configureEach { - reportUndocumented.set(true) - skipEmptyPackages.set(true) - skipDeprecated.set(true) - jdkVersion.set(11) - - // Add Android SDK packages - noAndroidSdkLink.set(false) - - sourceLink { - localDirectory.set(project.file("src/main/java")) - // URL showing where the source code can be accessed through the web browser - remoteUrl.set(new URL("https://github.com/halilozercan/compose-richtext/blob/main/${project.name}/src/main/java")) - // Suffix which is used to append the line number to the URL. Use #L for GitHub - remoteLineSuffix.set("#L") - } - } - } - } -} - -apply plugin: 'binary-compatibility-validator' -apiValidation { - // Ignore all sample projects, since they're not part of our API. - // Only leaf project name is valid configuration, and every project must be individually ignored. - // See https://github.com/Kotlin/binary-compatibility-validator/issues/3 - ignoredProjects += project('sample').name -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..080213f9 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,209 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +import com.android.build.gradle.LibraryExtension +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties +import org.jetbrains.dokka.gradle.DokkaMultiModuleTask +import org.jetbrains.dokka.gradle.DokkaTaskPartial +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +buildscript { + repositories { + mavenCentral() + gradlePluginPortal() + google() + } + + dependencies { + classpath(BuildPlugins.androidGradlePlugin) + classpath(Kotlin.binaryCompatibilityValidatorPlugin) + classpath(Kotlin.gradlePlugin) + classpath(ktlint) + } +} + +plugins { + id("org.jetbrains.dokka") version "1.5.0" +} + +repositories { + mavenCentral() +} + +tasks.withType().configureEach { + outputDirectory.set(rootProject.file("docs/api")) + failOnWarning.set(true) +} + +// See https://stackoverflow.com/questions/25324880/detect-ide-environment-with-gradle +fun isRunningFromIde(): Boolean { + return project.properties["android.injected.invoked.from.ide"] == "true" +} + +subprojects { + repositories { + google() + mavenCentral() + maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") } + } + + tasks.withType().all { + kotlinOptions { + // Allow warnings when running from IDE, makes it easier to experiment. + if (!isRunningFromIde()) { + allWarningsAsErrors = true + } + + freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") + } + } + + // taken from https://github.com/google/accompanist/blob/main/build.gradle + afterEvaluate { + if (tasks.findByName("dokkaHtmlPartial") == null) { + // If dokka isn't enabled on this module, skip + return@afterEvaluate + } + + tasks.named("dokkaHtmlPartial").configure { + dokkaSourceSets.configureEach { + reportUndocumented.set(true) + skipEmptyPackages.set(true) + skipDeprecated.set(true) + jdkVersion.set(11) + + // Add Android SDK packages + noAndroidSdkLink.set(false) + } + } + + val javadocJar by tasks.registering(Jar::class) { + dependsOn(tasks.dokkaJavadoc) + archiveClassifier.set("javadoc") + from(tasks.dokkaJavadoc.flatMap { it.outputDirectory }) + } + } + + afterEvaluate { + val androidExtension = extensions.findByType() + val multiplatformExtension = extensions.findByType() + + fun MavenPublication.configure() { + if (multiplatformExtension == null && androidExtension != null) { + val androidSourcesJar by tasks.registering(Jar::class) { + archiveClassifier.set("sources") + from(androidExtension.sourceSets["main"].java.srcDirs) + } + artifact(androidSourcesJar.get()) + from(components["release"]) + } + + artifact(tasks.named("javadocJar").get()) + + groupId = property("GROUP").toString() + artifactId = property("POM_ARTIFACT_ID").toString() + version = property("VERSION_NAME").toString() + + pom { + name.set(property("POM_NAME").toString()) + description.set(property("POM_DESCRIPTION").toString()) + url.set("https://github.com/halilozercan/compose-richtext") + + licenses { + license { + name.set("The Apache Software License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + distribution.set("repo") + } + } + developers { + developer { + id.set("halilozercan") + name.set("Halil Ozercan") + } + } + scm { + connection.set("scm:git:git://github.com/halilozercan/compose-richtext.git") + url.set("https://github.com/halilozercan/compose-richtext/") + developerConnection.set("scm:git:ssh://git@github.com/halilozercan/compose-richtext.git") + } + } + } + + extensions.findByType()?.apply { + repositories { + maven { + val localProperties = gradleLocalProperties(rootProject.rootDir) + + val sonatypeUsername = + localProperties.getProperty("SONATYPE_USERNAME") ?: System.getenv("SONATYPE_USERNAME") + + val sonatypePassword = + localProperties.getProperty("SONATYPE_PASSWORD") ?: System.getenv("SONATYPE_PASSWORD") + + val releasesRepoUrl = + uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2") + val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") + val version = property("VERSION_NAME").toString() + url = uri( + if (version.endsWith("SNAPSHOT")) { + snapshotsRepoUrl + } else { + releasesRepoUrl + } + ) + credentials { + username = sonatypeUsername + password = sonatypePassword + } + } + } + + if (multiplatformExtension != null) { + publications.withType().configureEach { + configure() + } + } else if (androidExtension != null) { + // Add publications for Android libraries. + // KMP libraries already have MavenPublications that are added by multiplatform plugin + publications.register("release") { + afterEvaluate { configure() } + } + } + } + + extensions.findByType()?.apply { + val localProperties = gradleLocalProperties(rootProject.rootDir) + + val gpgPrivateKey = + localProperties.getProperty("GPG_PRIVATE_KEY") + ?: System.getenv("GPG_PRIVATE_KEY") + ?: return@apply + + val gpgPrivatePassword = + localProperties.getProperty("GPG_PRIVATE_PASSWORD") + ?: System.getenv("GPG_PRIVATE_PASSWORD") + ?: return@apply + + val publishing = extensions.findByType() + ?: return@apply + + useInMemoryPgpKeys( + gpgPrivateKey.replace("\\n", "\n"), + gpgPrivatePassword + ) + sign(publishing.publications) + } + } +} + +//disable until the library reaches 1.0.0-beta01 +//apply plugin: 'binary-compatibility-validator' +//apiValidation { +// // Ignore all sample projects, since they're not part of our API. +// // Only leaf project name is valid configuration, and every project must be individually ignored. +// // See https://github.com/Kotlin/binary-compatibility-validator/issues/3 +// ignoredProjects += project('sample').name +// ignoredProjects += project('desktop').name +// ignoredProjects += project('richtext-ui-kmm').name +// ignoredProjects += project('richtext-commonmark-kmm').name +//} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..c8162f04 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,17 @@ +repositories { + google() + mavenCentral() +} + +plugins { + `kotlin-dsl` + `kotlin-dsl-precompiled-script-plugins` +} + +dependencies { + // keep in sync with Dependencies.BuildPlugins.androidGradlePlugin + implementation("com.android.tools.build:gradle:7.0.1") + // keep in sync with Dependencies.Kotlin.gradlePlugin + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21") + implementation(kotlin("script-runtime")) +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt new file mode 100644 index 00000000..b7afda47 --- /dev/null +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -0,0 +1,65 @@ +object BuildPlugins { + val androidGradlePlugin = "com.android.tools.build:gradle:7.0.1" +} + +object AndroidX { + val activity = "androidx.activity:activity:1.1.0" + val annotations = "androidx.annotation:annotation:1.1.0" + val appcompat = "androidx.appcompat:appcompat:1.3.0" + val constraintLayout = "androidx.constraintlayout:constraintlayout:1.1.3" + val fragment = "androidx.fragment:fragment:1.2.2" + val material = "com.google.android.material:material:1.1.0" + val recyclerview = "androidx.recyclerview:recyclerview:1.1.0" + val savedstate = "androidx.savedstate:savedstate:1.0.0" + val transition = "androidx.transition:transition:1.3.1" + val viewbinding = "androidx.databinding:viewbinding:3.6.1" +} + +object Network { + val okHttp = "com.squareup.okhttp3:okhttp:4.9.0" +} + +object Kotlin { + val version = "1.5.21" + val binaryCompatibilityValidatorPlugin = "org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0" + val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$version" + val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + val reflect = "org.jetbrains.kotlin:kotlin-reflect:$version" + + object Test { + val common = "org.jetbrains.kotlin:kotlin-test-common" + val annotations = "org.jetbrains.kotlin:kotlin-test-annotations-common" + val jdk = "org.jetbrains.kotlin:kotlin-test-junit" + val mockito = "com.nhaarman:mockito-kotlin-kt1.1:1.6.0" + } +} + +val ktlint = "org.jlleitschuh.gradle:ktlint-gradle:10.0.0" + +object Compose { + val version = "1.0.2" + val activity = "androidx.activity:activity-compose:1.3.0" + val foundation = "androidx.compose.foundation:foundation:$version" + val layout = "androidx.compose.foundation:foundation-layout:$version" + val material = "androidx.compose.material:material:$version" + val icons = "androidx.compose.material:material-icons-extended:$version" + val test = "androidx.ui:ui-test:$version" + val tooling = "androidx.compose.ui:ui-tooling:$version" + val toolingPreview = "androidx.compose.ui:ui-tooling-preview:$version" + val toolingData = "androidx.compose.ui:ui-tooling-data:$version" + val desktopPreview = "org.jetbrains.compose.ui:ui-tooling-preview-desktop:1.0.0-alpha3" + val coil = "io.coil-kt:coil-compose:1.3.2" +} + +object Commonmark { + private val version = "0.18.0" + val core = "org.commonmark:commonmark:$version" + val tables = "org.commonmark:commonmark-ext-gfm-tables:$version" + val strikethrough = "org.commonmark:commonmark-ext-gfm-strikethrough:$version" +} + +object AndroidConfiguration { + val minSdk = 21 + val targetSdk = 30 + val compileSdk = targetSdk +} diff --git a/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts b/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts new file mode 100644 index 00000000..919c16c9 --- /dev/null +++ b/buildSrc/src/main/kotlin/richtext-android-library.gradle.kts @@ -0,0 +1,31 @@ +plugins { + id("com.android.library") + kotlin("android") + id("maven-publish") + id("signing") +} + +kotlin { + explicitApi() +} + +android { + compileSdk = AndroidConfiguration.compileSdk + + defaultConfig { + minSdk = 21 + targetSdk = AndroidConfiguration.targetSdk + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = Compose.version + } + + lint { + disable("ComposableModifierFactory", "ModifierFactoryExtensionFunction", "ModifierFactoryReturnType", "ModifierFactoryUnreferencedReceiver") + } +} diff --git a/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts b/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts new file mode 100644 index 00000000..14d3b675 --- /dev/null +++ b/buildSrc/src/main/kotlin/richtext-kmp-library.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("com.android.library") + kotlin("multiplatform") + id("maven-publish") + id("signing") +} + +repositories { + google() + mavenCentral() +} + +kotlin { + jvm() + android { + publishLibraryVariants("release", "debug") + } + explicitApi() +} + +android { + compileSdk = 30 + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + defaultConfig { + minSdk = 21 + targetSdk = 30 + } +} diff --git a/desktop-sample/build.gradle.kts b/desktop-sample/build.gradle.kts new file mode 100644 index 00000000..0ba39d99 --- /dev/null +++ b/desktop-sample/build.gradle.kts @@ -0,0 +1,32 @@ +import org.jetbrains.compose.compose +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + kotlin("multiplatform") + id("org.jetbrains.compose") version "1.0.0-alpha3" +} + +kotlin { + jvm() + sourceSets { + val jvmMain by getting { + dependencies { + implementation(project(":richtext-commonmark")) + implementation(project(":richtext-ui-material")) + implementation(compose.desktop.currentOs) + } + } + val jvmTest by getting + } +} + +compose.desktop { + application { + mainClass = "MainKt" + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "jvm" + packageVersion = "1.0.0" + } + } +} \ No newline at end of file diff --git a/desktop-sample/src/jvmMain/kotlin/com/halilibo/richtext/desktop/Main.kt b/desktop-sample/src/jvmMain/kotlin/com/halilibo/richtext/desktop/Main.kt new file mode 100644 index 00000000..e46414b7 --- /dev/null +++ b/desktop-sample/src/jvmMain/kotlin/com/halilibo/richtext/desktop/Main.kt @@ -0,0 +1,272 @@ +package com.halilibo.richtext.desktop + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Surface +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.singleWindowApplication +import com.halilibo.richtext.markdown.Markdown +import com.halilibo.richtext.ui.material.MaterialRichText + +fun main(): Unit = singleWindowApplication( + title = "RichText KMP" +) { + Surface { + Row( + modifier = Modifier.padding(32.dp).fillMaxSize(), + horizontalArrangement = Arrangement.spacedBy(32.dp) + ) { + var text by remember { mutableStateOf(sampleMarkdown) } + BasicTextField( + value = text, + onValueChange = { text = it }, + maxLines = Int.MAX_VALUE, + modifier = Modifier.weight(1f) + .fillMaxHeight() + .background(Color.LightGray) + .padding(8.dp) + ) + MaterialRichText( + modifier = Modifier.weight(1f) + .verticalScroll(rememberScrollState()) + ) { + Markdown(content = text) + } + } + } +} + +private val sampleMarkdown = """ + # Demo + Based on [this cheatsheet][cheatsheet] + + --- + + ## Headers + --- + # Header 1 + ## Header 2 + ### Header 3 + #### Header 4 + ##### Header 5 + ###### Header 6 + --- + + ## Emphasis + + Emphasis, aka italics, with *asterisks* or _underscores_. + + Strong emphasis, aka bold, with **asterisks** or __underscores__. + + Combined emphasis with **asterisks and _underscores_**. + + --- + + ## Lists + 1. First ordered list item + 2. Another item + * Unordered sub-list. + 1. Actual numbers don't matter, just that it's a number + 1. Ordered sub-list + 4. And another item. + + You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we'll use three here to also align the raw Markdown). + + To have a line break without a paragraph, you will need to use two trailing spaces. + Note that this line is separate, but within the same paragraph. + (This is contrary to the typical GFM line break behaviour, where trailing spaces are not required.) + + * Unordered list can use asterisks + - Or minuses + + Or pluses + + --- + + ## Links + + [I'm an inline-style link](https://www.google.com) + + [I'm a reference-style link][Arbitrary case-insensitive reference text] + + [I'm a relative reference to a repository file](../blob/master/LICENSE) + + [You can use numbers for reference-style link definitions][1] + + Or leave it empty and use the [link text itself]. + + --- + + ## Code + + Inline `code` has `back-ticks around` it. + + ```javascript + var s = "JavaScript syntax highlighting"; + alert(s); + ``` + + ```python + s = "Python syntax highlighting" + print s + ``` + + ```java + /** + * Helper method to obtain a Parser with registered strike-through & table extensions + * & task lists (added in 1.0.1) + * + * @return a Parser instance that is supported by this library + * @since 1.0.0 + */ + @NonNull + public static Parser createParser() { + return new Parser.Builder() + .extensions(Arrays.asList( + StrikethroughExtension.create(), + TablesExtension.create(), + TaskListExtension.create() + )) + .build(); + } + ``` + + ```xml + + + + + + ``` + + ``` + No language indicated, so no syntax highlighting. + But let's throw in a tag. + ``` + + --- + + ## Images + + Inline-style: + + ![random image](https://picsum.photos/seed/picsum/400/400 "Text 1") + + Reference-style: + + ![random image][logo] + + [logo]: https://picsum.photos/seed/picsum2/400/400 "Text 2" + + --- + + ## Tables + + Colons can be used to align columns. + + | Tables | Are | Cool | + | ------------- |:-------------:| -----:| + | col 3 is | right-aligned | ${'$'}1600 | + | col 2 is | centered | ${'$'}12 | + | zebra stripes | are neat | ${'$'}1 | + + There must be at least 3 dashes separating each header cell. + The outer pipes (|) are optional, and you don't need to make the + raw Markdown line up prettily. You can also use inline Markdown. + + Markdown | Less | Pretty + --- | --- | --- + *Still* | `renders` | ![random image](https://picsum.photos/seed/picsum/400/400 "Text 1") + 1 | 2 | 3 + + --- + + ## Blockquotes + + > Blockquotes are very handy in email to emulate reply text. + > This line is part of the same quote. + + Quote break. + + > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. + + Nested quotes + > Hello! + >> And to you! + + --- + + ## Inline HTML + + ```html + HTML + ``` + + HTML + + --- + + ## Horizontal Rule + + Three or more... + + --- + + Hyphens (`-`) + + *** + + Asterisks (`*`) + + ___ + + Underscores (`_`) + + + ## License + + ``` + Copyright 2019 Dimitry Ivanov (legal@noties.io) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ``` + + [cheatsheet]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet + + [arbitrary case-insensitive reference text]: https://www.mozilla.org + [1]: http://slashdot.org + [link text itself]: http://www.reddit.com +""".trimIndent() \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index c5544141..d6c3c3cd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,10 @@ [![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0) Compose Richtext is a collection of Compose libraries for working with rich text formatting and -documents. +documents. + +`richtext-ui`, `richtext-commonmark`, and `richtext-material-ui` are Kotlin Multiplatform(KMP) Compose Libraries. +All 3 of these modules can be used in Android and Desktop Compose apps. Each library is documented separately, see the navigation menu for the list. This site also includes an API reference. @@ -25,4 +28,49 @@ dependencies { } ``` +There is no difference for KMP artifacts. For instance, if you are adding `richtext-ui` to a Kotlin Multiplatform module + +```kotlin +val commonMain by getting { + dependencies { + implementation("com.halilibo.compose-richtext:richtext-ui:${richtext_version}") + } +} +``` + +### Android + +Desktop Compose and Jetpack Compose for Android use the same modules but they are published under separate +artifacts. `org.jetbrains.compose` plugin replaces all `androidx.compose` dependencies with their `org.jetbrains.compose` counterparts. +If this is not done, gradle build fails with too many **Duplicate Class** errors. + +On the other hand, applying a KMP plugin in a pure Android App might not be the desired approach. Adding the following +configuration to `build.gradle` file in an Android module that depends on any of `RichText` KMP libraries would solve the problem as well. + +```groovy +configurations.all { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + if (details.requested.group.contains('org.jetbrains.compose')) { + def groupName = details.requested.group.replace("org.jetbrains.compose", "androidx.compose") + details.useTarget( + [group: groupName, name: details.requested.name, version: composeVersion] // compose version in your project + ) + } + } +} +``` + +Most importantly, this problem seems to be temporary. Jetbrains team is actively working on it. + +![A comment from Jetbrains in Compose Plugin docs.](https://github.com/JetBrains/compose-jb/blob/master/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt#L79) + +> It is temporarily solution until we will be publishing all MPP artifacts in Google Maven repository. Or align versions with androidx artifacts and point MPP-android artifacts to androidx artifacts (is it possible?) + +### Library Artifacts + The `LIBRARY_ARTIFACT`s for each individual library can be found on their respective pages. + +## Samples + +Please check out ![Android](https://github.com/halilozercan/compose-richtext/tree/main/sample) and ![Desktop](https://github.com/halilozercan/compose-richtext/tree/main/desktop) +projects to see various use cases of RichText in both platforms. \ No newline at end of file diff --git a/docs/printing.md b/docs/printing.md index d5637a78..1e6c16c6 100644 --- a/docs/printing.md +++ b/docs/printing.md @@ -1,5 +1,7 @@ # Printing +[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) + A library for using Compose to generated printed documents, using Android's printing services. ## Gradle diff --git a/docs/richtext-commonmark.md b/docs/richtext-commonmark.md index 5f35955c..70bc8b65 100644 --- a/docs/richtext-commonmark.md +++ b/docs/richtext-commonmark.md @@ -1,5 +1,8 @@ # Markdown +[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) +[![JVM Library](https://img.shields.io/badge/Platform-JVM-red.svg?style=for-the-badge)](https://kotlinlang.org/docs/mpp-intro.html) + Library for rendering Markdown in Compose using [CommonMark](https://github.com/commonmark/commonmark-java) library/spec to parse, and `richtext-ui` to render. @@ -13,11 +16,11 @@ dependencies { ## Usage -The simplest way to render markdown is just pass a string to the [`Markdown`](../api/richtext-commonmark/com.zachklipp.richtext.markdown/-markdown.html) +The simplest way to render markdown is just pass a string to the [`Markdown`](../api/richtext-commonmark/com.halilibo.richtext.markdown/-markdown.html) composable under RichText scope: !!! warning - Markdown composable has recently changed to be an extension on [RichTextScope](../api/richtext-ui/com.zachklipp.richtext.ui/-rich-text-scope/index.html) instead + Markdown composable has recently changed to be an extension on [RichTextScope](../api/richtext-ui/com.halilibo.richtext.ui/-rich-text-scope/index.html) instead of being a separate entry composable. ~~~kotlin diff --git a/docs/richtext-ui-material.md b/docs/richtext-ui-material.md index c0a80169..d61b4826 100644 --- a/docs/richtext-ui-material.md +++ b/docs/richtext-ui-material.md @@ -1,5 +1,8 @@ # Richtext UI Material +[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) +[![JVM Library](https://img.shields.io/badge/Platform-JVM-red.svg?style=for-the-badge)](https://kotlinlang.org/docs/mpp-intro.html) + Library that makes RichText compatible with Material design in Compose. ## Gradle @@ -14,7 +17,7 @@ dependencies { Material RichText library offers 2 different ways of integrating Material design with RichText in your app. -### MaterialRichText +### [`MaterialRichText`](../api/richtext-ui-material/com.halilibo.richtext.ui.material/-material-rich-text.html) `MaterialRichText` composable wraps around regular `RichText` while introducing the necessary integration dependencies. `MaterialRichText` shares the exact arguments with regular `RichText`. @@ -27,17 +30,19 @@ MaterialRichText(modifier = Modifier.background(color = Color.White)) { } ``` -### SetupMaterialRichText +### [`SetupMaterialRichText`](../api/richtext-ui-material/com.halilibo.richtext.ui.material/-setup-material-rich-text.html) If the whole application is written in Compose or contains large Compose trees, it would be ideal to call this function right after applying the Material Theme. Then, calling `MaterialRichText` or `RichText` would have no difference. ```kotlin -SetupMaterialRichText { - RichText(modifier = Modifier.background(color = Color.White)) { - Heading(0, "Paragraphs") - Text("Simple paragraph.") - ... +MaterialTheme(...) { + SetupMaterialRichText { + RichText(modifier = Modifier.background(color = Color.White)) { + Heading(0, "Paragraphs") + Text("Simple paragraph.") + ... + } } } ``` diff --git a/docs/richtext-ui.md b/docs/richtext-ui.md index dab8b988..adf3353d 100644 --- a/docs/richtext-ui.md +++ b/docs/richtext-ui.md @@ -1,5 +1,8 @@ # Richtext UI +[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) +[![JVM Library](https://img.shields.io/badge/Platform-JVM-red.svg?style=for-the-badge)](https://kotlinlang.org/docs/mpp-intro.html) + A library of composables for formatting text using higher-level concepts than are supported by compose foundation, such as "bullet lists" and "headings". @@ -15,7 +18,7 @@ dependencies { } ``` -## [`RichText`](../api/richtext-ui/com.zachklipp.richtext.ui/-basic-rich-text.html) +## [`RichText`](../api/richtext-ui/com.halilibo.richtext.ui/-rich-text.html) Richtext UI does not depend on Material artifact of Compose. Design agnostic API allows anyone to adopt RichText UI and its extensions like Markdown to their own design and typography systems. @@ -23,12 +26,12 @@ to adopt RichText UI and its extensions like Markdown to their own design and ty If you are planning to adopt RichText within your design system, please go ahead and check out [`RichText Material`](../richtext-ui-material/index.html) for inspiration. -## [`RichTextScope`](../api/richtext-ui/com.zachklipp.richtext.ui/-rich-text-scope/index.html) +## [`RichTextScope`](../api/richtext-ui/com.halilibo.richtext.ui/-rich-text-scope/index.html) `RichTextScope` is a context wrapper around composables that integrate and play well within RichText content. -## [`RichTextThemeIntegration`](../api/richtext-ui/com.zachklipp.richtext.ui/-rich-text-theme-integration.html) +## [`RichTextThemeIntegration`](../api/richtext-ui/com.halilibo.richtext.ui/-rich-text-theme-integration.html) Entry point for integrating app's own typography and theme system with RichText. diff --git a/docs/slideshow.md b/docs/slideshow.md index 160e764b..eba5060e 100644 --- a/docs/slideshow.md +++ b/docs/slideshow.md @@ -1,5 +1,7 @@ # Slideshow +[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) + A library for presenting simple Powerpoint-like slideshows from a phone (e.g. you can share your phone screen to a Google Hangout and present that way). Slides can contain any composable content, although a few pre-fab scaffolds are provided for common slide layouts. diff --git a/gradle.properties b/gradle.properties index 72773fd9..623091ac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=768m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects @@ -22,18 +22,8 @@ kotlin.code.style=official systemProp.org.gradle.internal.publish.checksums.insecure=true GROUP=com.halilibo.compose-richtext -VERSION_NAME=0.7.0 +VERSION_NAME=0.8.0-SNAPSHOT POM_DESCRIPTION=A collection of Compose libraries for advanced text formatting and alternative display types. -POM_URL=https://github.com/halilozercan/compose-richtext/ -POM_SCM_URL=https://github.com/halilozercan/compose-richtext/ -POM_SCM_CONNECTION=scm:git:git://github.com/halilozercan/compose-richtext.git -POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/halilozercan/compose-richtext.git - -POM_LICENCE_NAME=The Apache Software License, Version 2.0 -POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENCE_DIST=repo - -POM_DEVELOPER_ID=halilozercan -POM_DEVELOPER_NAME=Halil Ozercan +kotlin.mpp.stability.nowarn=true \ No newline at end of file diff --git a/gradle/maven-publish.gradle b/gradle/maven-publish.gradle deleted file mode 100644 index 0f432b56..00000000 --- a/gradle/maven-publish.gradle +++ /dev/null @@ -1,4 +0,0 @@ -apply plugin: 'com.vanniktech.maven.publish' - -group = GROUP -version = VERSION_NAME diff --git a/printing/build.gradle b/printing/build.gradle deleted file mode 100644 index 7b1b36de..00000000 --- a/printing/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -plugins { - id('org.jetbrains.dokka') -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply from: rootProject.file('gradle/maven-publish.gradle') - -android rootProject.ext.defaultAndroidConfig - -dependencies { - api deps.compose.foundation - implementation deps.compose.tooling - // For slot table analysis. - implementation deps.compose.tooling_data - implementation deps.androidx.activity - - // TODO Migrate off this. - implementation deps.compose.material -} - -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - freeCompilerArgs += ["-Xinline-classes"] - } -} diff --git a/printing/build.gradle.kts b/printing/build.gradle.kts new file mode 100644 index 00000000..91c3ef51 --- /dev/null +++ b/printing/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("richtext-android-library") + id("org.jetbrains.dokka") +} + +dependencies { + implementation(Compose.foundation) + implementation(Compose.tooling) + // For slot table analysis. + implementation(Compose.toolingData) + implementation(AndroidX.activity) + + // TODO Migrate off this. + implementation(Compose.material) +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java).all { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + "-Xinline-classes" + } +} diff --git a/richtext-commonmark/api/richtext-commonmark.api b/richtext-commonmark/api/richtext-commonmark.api deleted file mode 100644 index 3811f251..00000000 --- a/richtext-commonmark/api/richtext-commonmark.api +++ /dev/null @@ -1,20 +0,0 @@ -public final class com/zachklipp/richtext/markdown/BuildConfig { - public static final field BUILD_TYPE Ljava/lang/String; - public static final field DEBUG Z - public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; - public fun ()V -} - -public final class com/zachklipp/richtext/markdown/ComposableSingletons$MarkdownKt { - public static final field INSTANCE Lcom/zachklipp/richtext/markdown/ComposableSingletons$MarkdownKt; - public static field lambda-1 Lkotlin/jvm/functions/Function4; - public static field lambda-2 Lkotlin/jvm/functions/Function4; - public fun ()V - public final fun getLambda-1$richtext_commonmark_release ()Lkotlin/jvm/functions/Function4; - public final fun getLambda-2$richtext_commonmark_release ()Lkotlin/jvm/functions/Function4; -} - -public final class com/zachklipp/richtext/markdown/MarkdownKt { - public static final fun Markdown (Lcom/zachklipp/richtext/ui/RichTextScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V -} - diff --git a/richtext-commonmark/build.gradle b/richtext-commonmark/build.gradle deleted file mode 100644 index 1b91b6a1..00000000 --- a/richtext-commonmark/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -plugins { - id('org.jetbrains.dokka') -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply from: rootProject.file('gradle/maven-publish.gradle') - -android rootProject.ext.defaultAndroidConfig - -dependencies { - compileOnly deps.compose.tooling - - api project(":richtext-ui") - - implementation deps.coil - implementation deps.commonmark.core - implementation deps.commonmark.strikethrough - implementation deps.commonmark.tables - - // TODO Migrate off this. - implementation deps.compose.material -} diff --git a/richtext-commonmark/build.gradle.kts b/richtext-commonmark/build.gradle.kts new file mode 100644 index 00000000..5422a27f --- /dev/null +++ b/richtext-commonmark/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + id("richtext-kmp-library") + id("org.jetbrains.compose") version "1.0.0-alpha3" + id("org.jetbrains.dokka") +} + +repositories { + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") +} + +kotlin { + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + api(project(":richtext-ui")) + } + } + val commonTest by getting + + val androidMain by getting { + kotlin.srcDir("src/commonJvmAndroid/kotlin") + dependencies { + implementation(Compose.coil) + + implementation(Commonmark.core) + implementation(Commonmark.tables) + implementation(Commonmark.strikethrough) + } + } + + val jvmMain by getting { + kotlin.srcDir("src/commonJvmAndroid/kotlin") + dependencies { + implementation(compose.desktop.currentOs) + implementation(Network.okHttp) + + implementation(Commonmark.core) + implementation(Commonmark.tables) + implementation(Commonmark.strikethrough) + } + } + } +} diff --git a/richtext-commonmark/consumer-rules.pro b/richtext-commonmark/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/richtext-commonmark/gradle.properties b/richtext-commonmark/gradle.properties index b3e57cbc..8336656c 100644 --- a/richtext-commonmark/gradle.properties +++ b/richtext-commonmark/gradle.properties @@ -1,4 +1,4 @@ POM_ARTIFACT_ID=richtext-commonmark POM_NAME=Compose Richtext Commonmark POM_DESCRIPTION=A library for rendering markdown in Compose using the Commonmark library. -POM_PACKAGING=aar +POM_PACKAGING=aar \ No newline at end of file diff --git a/richtext-commonmark/src/androidMain/AndroidManifest.xml b/richtext-commonmark/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..d3878ea6 --- /dev/null +++ b/richtext-commonmark/src/androidMain/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt new file mode 100644 index 00000000..ec205d83 --- /dev/null +++ b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt @@ -0,0 +1,26 @@ +package com.halilibo.richtext.markdown + +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES +import android.text.Html +import android.widget.TextView +import androidx.compose.runtime.Composable +import androidx.compose.ui.viewinterop.AndroidView + +@Composable +internal actual fun HtmlBlock(content: String) { + AndroidView( + factory = { context -> + // TODO: pass current styling to legacy TextView + TextView(context) + }, + update = { + it.text = if (VERSION.SDK_INT >= VERSION_CODES.N) { + Html.fromHtml(content, 0) + } else { + @Suppress("DEPRECATION") + Html.fromHtml(content) + } + } + ) +} diff --git a/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt new file mode 100644 index 00000000..4fb37ad1 --- /dev/null +++ b/richtext-commonmark/src/androidMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt @@ -0,0 +1,73 @@ +package com.halilibo.richtext.markdown + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.isSpecified +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.dp +import coil.annotation.ExperimentalCoilApi +import coil.compose.rememberImagePainter + +private val DEFAULT_IMAGE_SIZE = 64.dp + +/** + * Implementation of RemoteImage by using Coil library for Android. + */ +@OptIn(ExperimentalCoilApi::class) +@Composable +internal actual fun RemoteImage( + url: String, + contentDescription: String?, + modifier: Modifier, + contentScale: ContentScale +) { + val painter = rememberImagePainter(data = url) + + val density = LocalDensity.current + + BoxWithConstraints { + val sizeModifier by remember(density, painter) { + derivedStateOf { + val painterIntrinsicSize = painter.state.painter?.intrinsicSize + if (painterIntrinsicSize != null && + painterIntrinsicSize.isSpecified && + painterIntrinsicSize.width != Float.POSITIVE_INFINITY && + painterIntrinsicSize.height != Float.POSITIVE_INFINITY + ) { + val width = painterIntrinsicSize.width + val height = painterIntrinsicSize.height + val scale = if (width > constraints.maxWidth) { + constraints.maxWidth.toFloat() / width + } else { + 1f + } + + with(density) { + Modifier.size( + (width * scale).toDp(), + (height * scale).toDp() + ) + } + } else { + // if size is not defined at all, Coil fails to render the image + // here, we give a default size for images until they are loaded. + Modifier.size(DEFAULT_IMAGE_SIZE) + } + } + } + + Image( + painter = painter, + contentDescription = contentDescription, + modifier = sizeModifier, + contentScale = contentScale + ) + } +} diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/commonmark/AstNodeConvert.kt b/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt similarity index 59% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/commonmark/AstNodeConvert.kt rename to richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt index e1d61420..724d7498 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/commonmark/AstNodeConvert.kt +++ b/richtext-commonmark/src/commonJvmAndroid/kotlin/com/halilibo/richtext/markdown/AstNodeConvert.kt @@ -1,37 +1,42 @@ -package com.zachklipp.richtext.markdown.commonmark +package com.halilibo.richtext.markdown -import com.zachklipp.richtext.markdown.node.AstBlockQuote -import com.zachklipp.richtext.markdown.node.AstBulletList -import com.zachklipp.richtext.markdown.node.AstCode -import com.zachklipp.richtext.markdown.node.AstDocument -import com.zachklipp.richtext.markdown.node.AstEmphasis -import com.zachklipp.richtext.markdown.node.AstFencedCodeBlock -import com.zachklipp.richtext.markdown.node.AstHardLineBreak -import com.zachklipp.richtext.markdown.node.AstHeading -import com.zachklipp.richtext.markdown.node.AstHtmlBlock -import com.zachklipp.richtext.markdown.node.AstHtmlInline -import com.zachklipp.richtext.markdown.node.AstImage -import com.zachklipp.richtext.markdown.node.AstIndentedCodeBlock -import com.zachklipp.richtext.markdown.node.AstLink -import com.zachklipp.richtext.markdown.node.AstLinkReferenceDefinition -import com.zachklipp.richtext.markdown.node.AstListItem -import com.zachklipp.richtext.markdown.node.AstNode -import com.zachklipp.richtext.markdown.node.AstNodeLinks -import com.zachklipp.richtext.markdown.node.AstNodeType -import com.zachklipp.richtext.markdown.node.AstOrderedList -import com.zachklipp.richtext.markdown.node.AstParagraph -import com.zachklipp.richtext.markdown.node.AstSoftLineBreak -import com.zachklipp.richtext.markdown.node.AstStrikethrough -import com.zachklipp.richtext.markdown.node.AstStrongEmphasis -import com.zachklipp.richtext.markdown.node.AstTableBody -import com.zachklipp.richtext.markdown.node.AstTableCell -import com.zachklipp.richtext.markdown.node.AstTableCellAlignment -import com.zachklipp.richtext.markdown.node.AstTableHeader -import com.zachklipp.richtext.markdown.node.AstTableRoot -import com.zachklipp.richtext.markdown.node.AstTableRow -import com.zachklipp.richtext.markdown.node.AstText -import com.zachklipp.richtext.markdown.node.AstThematicBreak +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import com.halilibo.richtext.markdown.node.AstBlockQuote +import com.halilibo.richtext.markdown.node.AstBulletList +import com.halilibo.richtext.markdown.node.AstCode +import com.halilibo.richtext.markdown.node.AstDocument +import com.halilibo.richtext.markdown.node.AstEmphasis +import com.halilibo.richtext.markdown.node.AstFencedCodeBlock +import com.halilibo.richtext.markdown.node.AstHardLineBreak +import com.halilibo.richtext.markdown.node.AstHeading +import com.halilibo.richtext.markdown.node.AstHtmlBlock +import com.halilibo.richtext.markdown.node.AstHtmlInline +import com.halilibo.richtext.markdown.node.AstImage +import com.halilibo.richtext.markdown.node.AstIndentedCodeBlock +import com.halilibo.richtext.markdown.node.AstLink +import com.halilibo.richtext.markdown.node.AstLinkReferenceDefinition +import com.halilibo.richtext.markdown.node.AstListItem +import com.halilibo.richtext.markdown.node.AstNode +import com.halilibo.richtext.markdown.node.AstNodeLinks +import com.halilibo.richtext.markdown.node.AstNodeType +import com.halilibo.richtext.markdown.node.AstOrderedList +import com.halilibo.richtext.markdown.node.AstParagraph +import com.halilibo.richtext.markdown.node.AstSoftLineBreak +import com.halilibo.richtext.markdown.node.AstStrikethrough +import com.halilibo.richtext.markdown.node.AstStrongEmphasis +import com.halilibo.richtext.markdown.node.AstTableBody +import com.halilibo.richtext.markdown.node.AstTableCell +import com.halilibo.richtext.markdown.node.AstTableCellAlignment +import com.halilibo.richtext.markdown.node.AstTableHeader +import com.halilibo.richtext.markdown.node.AstTableRoot +import com.halilibo.richtext.markdown.node.AstTableRow +import com.halilibo.richtext.markdown.node.AstText +import com.halilibo.richtext.markdown.node.AstThematicBreak import org.commonmark.ext.gfm.strikethrough.Strikethrough +import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension import org.commonmark.ext.gfm.tables.TableBlock import org.commonmark.ext.gfm.tables.TableBody import org.commonmark.ext.gfm.tables.TableCell @@ -40,6 +45,7 @@ import org.commonmark.ext.gfm.tables.TableCell.Alignment.LEFT import org.commonmark.ext.gfm.tables.TableCell.Alignment.RIGHT import org.commonmark.ext.gfm.tables.TableHead import org.commonmark.ext.gfm.tables.TableRow +import org.commonmark.ext.gfm.tables.TablesExtension import org.commonmark.node.BlockQuote import org.commonmark.node.BulletList import org.commonmark.node.Code @@ -64,6 +70,7 @@ import org.commonmark.node.SoftLineBreak import org.commonmark.node.StrongEmphasis import org.commonmark.node.Text import org.commonmark.node.ThematicBreak +import org.commonmark.parser.Parser /** * Converts common-markdown tree to AstNode tree in a recursive fashion. @@ -104,10 +111,17 @@ internal fun convert( is HtmlBlock -> AstHtmlBlock( literal = node.literal ) - is Image -> AstImage( - title = node.title, - destination = node.destination - ) + is Image -> { + if (node.title == null || node.destination == null) { + null + } + else { + AstImage( + title = node.title, + destination = node.destination + ) + } + } is IndentedCodeBlock -> AstIndentedCodeBlock( literal = node.literal ) @@ -144,6 +158,7 @@ internal fun convert( CENTER -> AstTableCellAlignment.CENTER RIGHT -> AstTableCellAlignment.RIGHT null -> AstTableCellAlignment.LEFT + else -> AstTableCellAlignment.LEFT } ) is Strikethrough -> AstStrikethrough( @@ -168,4 +183,27 @@ internal fun convert( } return newNode -} \ No newline at end of file +} + +internal fun Node.convert() = convert(this) + +@Composable +internal actual fun parsedMarkdownAst(text: String): AstNode? { + val parser = remember { + Parser.builder() + .extensions( + listOf( + TablesExtension.create(), + StrikethroughExtension.create() + ) + ) + .build() + } + + val astRootNode by produceState(null, text) { + value = parser.parse(text).convert() + } + + return astRootNode +} + diff --git a/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt new file mode 100644 index 00000000..8aaae527 --- /dev/null +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt @@ -0,0 +1,10 @@ +package com.halilibo.richtext.markdown + +import androidx.compose.runtime.Composable + +/** + * Android and JVM can have different WebView or HTML rendering implementations. + * We are leaving HTML rendering to platform side. + */ +@Composable +internal expect fun HtmlBlock(content: String) diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/Markdown.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/Markdown.kt similarity index 59% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/Markdown.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/Markdown.kt index d059d098..61c5c3b7 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/Markdown.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/Markdown.kt @@ -1,56 +1,42 @@ -package com.zachklipp.richtext.markdown +package com.halilibo.richtext.markdown -import android.annotation.SuppressLint -import android.os.Build.VERSION -import android.os.Build.VERSION_CODES -import android.text.Html -import android.util.Log -import android.widget.TextView -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.viewinterop.AndroidView -import com.zachklipp.richtext.markdown.node.AstBlockQuote -import com.zachklipp.richtext.markdown.node.AstBulletList -import com.zachklipp.richtext.markdown.node.AstDocument -import com.zachklipp.richtext.markdown.node.AstFencedCodeBlock -import com.zachklipp.richtext.markdown.node.AstHeading -import com.zachklipp.richtext.markdown.node.AstHtmlBlock -import com.zachklipp.richtext.markdown.node.AstIndentedCodeBlock -import com.zachklipp.richtext.markdown.node.AstInlineNodeType -import com.zachklipp.richtext.markdown.node.AstLinkReferenceDefinition -import com.zachklipp.richtext.markdown.node.AstListItem -import com.zachklipp.richtext.markdown.node.AstNode -import com.zachklipp.richtext.markdown.node.AstOrderedList -import com.zachklipp.richtext.markdown.node.AstParagraph -import com.zachklipp.richtext.markdown.node.AstTableBody -import com.zachklipp.richtext.markdown.node.AstTableCell -import com.zachklipp.richtext.markdown.node.AstTableHeader -import com.zachklipp.richtext.markdown.node.AstTableRoot -import com.zachklipp.richtext.markdown.node.AstTableRow -import com.zachklipp.richtext.markdown.node.AstText -import com.zachklipp.richtext.markdown.node.AstThematicBreak -import com.zachklipp.richtext.markdown.commonmark.convert -import com.zachklipp.richtext.ui.BlockQuote -import com.zachklipp.richtext.ui.CodeBlock -import com.zachklipp.richtext.ui.FormattedList -import com.zachklipp.richtext.ui.Heading -import com.zachklipp.richtext.ui.HorizontalRule -import com.zachklipp.richtext.ui.ListType.Ordered -import com.zachklipp.richtext.ui.ListType.Unordered -import com.zachklipp.richtext.ui.RichTextScope -import com.zachklipp.richtext.ui.string.InlineContent -import com.zachklipp.richtext.ui.string.Text -import com.zachklipp.richtext.ui.string.richTextString -import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension -import org.commonmark.ext.gfm.tables.TablesExtension -import org.commonmark.parser.Parser +import com.halilibo.richtext.markdown.node.AstBlockQuote +import com.halilibo.richtext.markdown.node.AstBulletList +import com.halilibo.richtext.markdown.node.AstDocument +import com.halilibo.richtext.markdown.node.AstFencedCodeBlock +import com.halilibo.richtext.markdown.node.AstHeading +import com.halilibo.richtext.markdown.node.AstHtmlBlock +import com.halilibo.richtext.markdown.node.AstIndentedCodeBlock +import com.halilibo.richtext.markdown.node.AstInlineNodeType +import com.halilibo.richtext.markdown.node.AstLinkReferenceDefinition +import com.halilibo.richtext.markdown.node.AstListItem +import com.halilibo.richtext.markdown.node.AstNode +import com.halilibo.richtext.markdown.node.AstOrderedList +import com.halilibo.richtext.markdown.node.AstParagraph +import com.halilibo.richtext.markdown.node.AstTableBody +import com.halilibo.richtext.markdown.node.AstTableCell +import com.halilibo.richtext.markdown.node.AstTableHeader +import com.halilibo.richtext.markdown.node.AstTableRoot +import com.halilibo.richtext.markdown.node.AstTableRow +import com.halilibo.richtext.markdown.node.AstText +import com.halilibo.richtext.markdown.node.AstThematicBreak +import com.halilibo.richtext.ui.BlockQuote +import com.halilibo.richtext.ui.CodeBlock +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.Heading +import com.halilibo.richtext.ui.HorizontalRule +import com.halilibo.richtext.ui.ListType.Ordered +import com.halilibo.richtext.ui.ListType.Unordered +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.string.InlineContent +import com.halilibo.richtext.ui.string.Text +import com.halilibo.richtext.ui.string.richTextString /** * A composable that renders Markdown content using RichText. @@ -78,6 +64,15 @@ public fun RichTextScope.Markdown( } } +/** + * Parse markdown content and return Abstract Syntax Tree(AST). + * Composable is efficient thanks to remember construct. + * + * @param text Markdown text to be parsed. + */ +@Composable +internal expect fun parsedMarkdownAst(text: String): AstNode? + /** * When parsed, markdown content or any other rich text can be represented as a tree. * The default markdown parser that is used in this project `common-markdown` also @@ -148,20 +143,7 @@ internal fun RichTextScope.RecursiveRenderMarkdownAst(astNode: AstNode?) { is AstHtmlBlock -> { Text(text = richTextString { appendInlineContent(content = InlineContent { - AndroidView( - factory = { context -> - // TODO: pass current styling to legacy TextView - TextView(context) - }, - update = { - it.text = if (VERSION.SDK_INT >= VERSION_CODES.N) { - Html.fromHtml(astNodeType.literal, 0) - } else { - @Suppress("DEPRECATION") - Html.fromHtml(astNodeType.literal) - } - } - ) + HtmlBlock(astNodeType.literal) }) }) } @@ -180,56 +162,31 @@ internal fun RichTextScope.RecursiveRenderMarkdownAst(astNode: AstNode?) { // In any case, we should include it here to prevent any // non-rendered text problems. is AstText -> { - Log.e("MarkdownRichText", "Unexpected raw text while traversing the Abstract Syntax Tree.") - Text(astNodeType.literal) + // TODO(halilozercan) use multiplatform compatible stderr logging + println("Unexpected raw text while traversing the Abstract Syntax Tree.") + Text(richTextString { append(astNodeType.literal) }) } is AstListItem -> { - Log.e("MarkdownRichText", "Unexpected AstListItem while traversing the Abstract Syntax Tree.") + println("MarkdownRichText: Unexpected AstListItem while traversing the Abstract Syntax Tree.") } is AstInlineNodeType -> { // ignore - Log.e("MarkdownRichText", "Unexpected AstInlineNodeType ${astNodeType} while traversing the Abstract Syntax Tree.") + println("MarkdownRichText: Unexpected AstInlineNodeType $astNodeType while traversing the Abstract Syntax Tree.") } AstTableBody, AstTableHeader, AstTableRow, is AstTableCell -> { - Log.e("MarkdownRichText", "Unexpected Table node while traversing the Abstract Syntax Tree.") + println("MarkdownRichText: Unexpected Table node while traversing the Abstract Syntax Tree.") } }.let {} } -/** - * Parse markdown content and return Abstract Syntax Tree(AST). - * Composable is efficient thanks to remember construct. - * - * @param text Markdown text to be parsed. - */ -@Composable -internal fun parsedMarkdownAst(text: String): AstNode? { - val parser = remember { - Parser.builder() - .extensions( - listOf( - TablesExtension.create(), - StrikethroughExtension.create() - ) - ).build() - } - - val rootASTNode by produceState(null, text) { - value = convert(parser.parse(text)) - } - - return rootASTNode -} - /** * Visit and render children from first to last. * * @param node Root ASTNode whose children will be visited. */ -@SuppressLint("ComposableNaming") @Composable internal fun RichTextScope.visitChildren(node: AstNode?) { node?.childrenSequence()?.forEach { diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/MarkdownRichText.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/MarkdownRichText.kt similarity index 52% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/MarkdownRichText.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/MarkdownRichText.kt index 497b76b3..5f3a8fe8 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/MarkdownRichText.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/MarkdownRichText.kt @@ -1,43 +1,36 @@ -package com.zachklipp.richtext.markdown +package com.halilibo.richtext.markdown -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.isSpecified +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import coil.annotation.ExperimentalCoilApi -import coil.compose.rememberImagePainter -import com.zachklipp.richtext.markdown.node.AstCode -import com.zachklipp.richtext.markdown.node.AstEmphasis -import com.zachklipp.richtext.markdown.node.AstHardLineBreak -import com.zachklipp.richtext.markdown.node.AstImage -import com.zachklipp.richtext.markdown.node.AstLink -import com.zachklipp.richtext.markdown.node.AstLinkReferenceDefinition -import com.zachklipp.richtext.markdown.node.AstNode -import com.zachklipp.richtext.markdown.node.AstBlockQuote -import com.zachklipp.richtext.markdown.node.AstFencedCodeBlock -import com.zachklipp.richtext.markdown.node.AstHeading -import com.zachklipp.richtext.markdown.node.AstParagraph -import com.zachklipp.richtext.markdown.node.AstIndentedCodeBlock -import com.zachklipp.richtext.markdown.node.AstSoftLineBreak -import com.zachklipp.richtext.markdown.node.AstStrikethrough -import com.zachklipp.richtext.markdown.node.AstStrongEmphasis -import com.zachklipp.richtext.markdown.node.AstText -import com.zachklipp.richtext.markdown.node.AstListItem -import com.zachklipp.richtext.ui.BlockQuote -import com.zachklipp.richtext.ui.FormattedList -import com.zachklipp.richtext.ui.RichTextScope -import com.zachklipp.richtext.ui.string.InlineContent -import com.zachklipp.richtext.ui.string.RichTextString -import com.zachklipp.richtext.ui.string.withFormat -import java.util.* -import com.zachklipp.richtext.ui.string.Text as InlineRichText +import com.halilibo.richtext.markdown.node.AstBlockQuote +import com.halilibo.richtext.markdown.node.AstCode +import com.halilibo.richtext.markdown.node.AstEmphasis +import com.halilibo.richtext.markdown.node.AstFencedCodeBlock +import com.halilibo.richtext.markdown.node.AstHardLineBreak +import com.halilibo.richtext.markdown.node.AstHeading +import com.halilibo.richtext.markdown.node.AstImage +import com.halilibo.richtext.markdown.node.AstIndentedCodeBlock +import com.halilibo.richtext.markdown.node.AstLink +import com.halilibo.richtext.markdown.node.AstLinkReferenceDefinition +import com.halilibo.richtext.markdown.node.AstListItem +import com.halilibo.richtext.markdown.node.AstNode +import com.halilibo.richtext.markdown.node.AstParagraph +import com.halilibo.richtext.markdown.node.AstSoftLineBreak +import com.halilibo.richtext.markdown.node.AstStrikethrough +import com.halilibo.richtext.markdown.node.AstStrongEmphasis +import com.halilibo.richtext.markdown.node.AstText +import com.halilibo.richtext.ui.BlockQuote +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.string.InlineContent +import com.halilibo.richtext.ui.string.RichTextString +import com.halilibo.richtext.ui.string.Text +import com.halilibo.richtext.ui.string.withFormat /** * Only render the text content that exists below [astNode]. All the content blocks @@ -70,10 +63,9 @@ internal fun RichTextScope.MarkdownRichText(astNode: AstNode) { computeRichTextString(astNode, onLinkClicked) } - InlineRichText(text = richText) + Text(text = richText) } -@OptIn(ExperimentalCoilApi::class) private fun computeRichTextString( astNode: AstNode, onLinkClicked: (String) -> Unit @@ -81,18 +73,17 @@ private fun computeRichTextString( val richTextStringBuilder = RichTextString.Builder() // Modified pre-order traversal with pushFormat, popFormat support. - val iteratorStack = LinkedList().apply { - addFirst( - AstNodeTraversalEntry( - astNode = astNode, - isVisited = false, - formatIndex = null - ) + var iteratorStack = listOf( + AstNodeTraversalEntry( + astNode = astNode, + isVisited = false, + formatIndex = null ) - } + ) while (iteratorStack.isNotEmpty()) { - val (currentNode, isVisited, formatIndex) = iteratorStack.removeFirst() + val (currentNode, isVisited, formatIndex) = iteratorStack.first().copy() + iteratorStack = iteratorStack.drop(1) if (!isVisited) { val newFormatIndex = when (val currentNodeType = currentNode.type) { @@ -108,9 +99,18 @@ private fun computeRichTextString( ) is AstImage -> { richTextStringBuilder.appendInlineContent( - content = inlineImageContent( - currentNodeType.title, currentNodeType.destination - ) + content = InlineContent( + initialSize = { + IntSize(128.dp.roundToPx(), 128.dp.roundToPx()) + } + ) { + RemoteImage( + url = currentNodeType.destination, + contentDescription = currentNodeType.title, + modifier = Modifier.fillMaxWidth(), + contentScale = ContentScale.Inside + ) + } ) null } @@ -137,7 +137,7 @@ private fun computeRichTextString( else -> null } - iteratorStack.addFirst( + iteratorStack = iteratorStack.addFirst( AstNodeTraversalEntry( astNode = currentNode, isVisited = true, @@ -148,7 +148,7 @@ private fun computeRichTextString( // Do not visit children of terminals such as Text, Image, etc. if (!currentNode.isRichTextTerminal()) { currentNode.childrenSequence(reverse = true).forEach { - iteratorStack.addFirst( + iteratorStack = iteratorStack.addFirst( AstNodeTraversalEntry( astNode = it, isVisited = false, @@ -167,59 +167,12 @@ private fun computeRichTextString( return richTextStringBuilder.toRichTextString() } -//TODO(halilozercan): This should be provided from consumer side. -@OptIn(ExperimentalCoilApi::class) -private fun inlineImageContent( - title: String, - destination: String -): InlineContent { - return InlineContent( - initialSize = { - IntSize(128.dp.roundToPx(), 128.dp.roundToPx()) - } - ) { - val painter = rememberImagePainter( - data = destination - ) - - BoxWithConstraints { - val sizeModifier by remember { - derivedStateOf { - val painterIntrinsicSize = painter.state.painter?.intrinsicSize - if (painterIntrinsicSize != null && - painterIntrinsicSize.isSpecified && - painterIntrinsicSize.width != Float.POSITIVE_INFINITY && - painterIntrinsicSize.height != Float.POSITIVE_INFINITY - ) { - val width = painterIntrinsicSize.width - val height = painterIntrinsicSize.height - val scale = if (width > constraints.maxWidth) { - constraints.maxWidth.toFloat() / width - } else { - 1f - } - - Modifier.size( - (width * scale).toDp(), - (height * scale).toDp() - ) - } else { - Modifier.size(128.dp) - } - } - } - - Image( - painter = painter, - contentDescription = title, - modifier = sizeModifier - ) - } - } -} - private data class AstNodeTraversalEntry( val astNode: AstNode, val isVisited: Boolean, val formatIndex: Int? ) + +private inline fun List.addFirst(item: T): List { + return listOf(item) + this +} diff --git a/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt new file mode 100644 index 00000000..f665ae8c --- /dev/null +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt @@ -0,0 +1,18 @@ +package com.halilibo.richtext.markdown + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale + +//TODO(halilozercan): This should be provided from consumer side. +/** + * Image rendering is highly platform dependent. Coil is the desired + * way to show images but it doesn't exist in desktop. + */ +@Composable +internal expect fun RemoteImage( + url: String, + contentDescription: String?, + modifier: Modifier = Modifier, + contentScale: ContentScale +) diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/RenderTable.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RenderTable.kt similarity index 63% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/RenderTable.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RenderTable.kt index ae0ae464..17e933fd 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/RenderTable.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/RenderTable.kt @@ -1,14 +1,13 @@ -package com.zachklipp.richtext.markdown +package com.halilibo.richtext.markdown import androidx.compose.runtime.Composable -import com.zachklipp.richtext.markdown.node.AstNode -import com.zachklipp.richtext.markdown.node.AstTableBody -import com.zachklipp.richtext.markdown.node.AstTableCell -import com.zachklipp.richtext.markdown.node.AstTableHeader -import com.zachklipp.richtext.markdown.node.AstTableRoot -import com.zachklipp.richtext.markdown.node.AstTableRow -import com.zachklipp.richtext.ui.RichTextScope -import com.zachklipp.richtext.ui.Table +import com.halilibo.richtext.markdown.node.AstNode +import com.halilibo.richtext.markdown.node.AstTableBody +import com.halilibo.richtext.markdown.node.AstTableCell +import com.halilibo.richtext.markdown.node.AstTableHeader +import com.halilibo.richtext.markdown.node.AstTableRow +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.Table @Composable internal fun RichTextScope.RenderTable(node: AstNode) { diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/TraverseUtils.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/TraverseUtils.kt similarity index 64% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/TraverseUtils.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/TraverseUtils.kt index 27493033..5ef4ae0d 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/TraverseUtils.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/TraverseUtils.kt @@ -1,8 +1,12 @@ -package com.zachklipp.richtext.markdown +package com.halilibo.richtext.markdown -import com.zachklipp.richtext.markdown.node.AstInlineNodeType -import com.zachklipp.richtext.markdown.node.AstNode -import com.zachklipp.richtext.markdown.node.AstNodeType +import com.halilibo.richtext.markdown.node.AstCode +import com.halilibo.richtext.markdown.node.AstHardLineBreak +import com.halilibo.richtext.markdown.node.AstImage +import com.halilibo.richtext.markdown.node.AstNode +import com.halilibo.richtext.markdown.node.AstNodeType +import com.halilibo.richtext.markdown.node.AstSoftLineBreak +import com.halilibo.richtext.markdown.node.AstText internal fun AstNode.childrenSequence( reverse: Boolean = false @@ -37,5 +41,9 @@ internal inline fun AstNode.filterChildrenType(): Sequ * These ASTNode types should never have any children. If any exists, ignore them. */ internal fun AstNode.isRichTextTerminal(): Boolean { - return type is AstInlineNodeType + return type is AstText + || type is AstCode + || type is AstImage + || type is AstSoftLineBreak + || type is AstHardLineBreak } diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNode.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNode.kt similarity index 87% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNode.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNode.kt index 39d12157..c0a7a087 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNode.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNode.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.markdown.node +package com.halilibo.richtext.markdown.node /** * Generic AstNode implementation that can define any node in Abstract Syntax Tree. diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeLinks.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeLinks.kt similarity index 94% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeLinks.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeLinks.kt index e7f773f7..3c23665a 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeLinks.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeLinks.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.markdown.node +package com.halilibo.richtext.markdown.node import androidx.compose.runtime.Immutable diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeType.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeType.kt similarity index 97% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeType.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeType.kt index faf5cf4a..3d53e6d3 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstNodeType.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeType.kt @@ -1,7 +1,7 @@ -package com.zachklipp.richtext.markdown.node +package com.halilibo.richtext.markdown.node import androidx.compose.runtime.Immutable -import com.zachklipp.richtext.ui.string.RichTextString +import com.halilibo.richtext.ui.string.RichTextString /** * Refer to https://spec.commonmark.org/0.30/#precedence diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstStrikethrough.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstStrikethrough.kt similarity index 75% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstStrikethrough.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstStrikethrough.kt index d29af957..1b9a2d3d 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstStrikethrough.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstStrikethrough.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.markdown.node +package com.halilibo.richtext.markdown.node import androidx.compose.runtime.Immutable diff --git a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstTable.kt b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstTable.kt similarity index 92% rename from richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstTable.kt rename to richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstTable.kt index 1cf59720..90d08a7e 100644 --- a/richtext-commonmark/src/main/java/com/zachklipp/richtext/markdown/node/AstTable.kt +++ b/richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstTable.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.markdown.node +package com.halilibo.richtext.markdown.node import androidx.compose.runtime.Immutable diff --git a/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt b/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt new file mode 100644 index 00000000..8ad94069 --- /dev/null +++ b/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/HtmlBlock.kt @@ -0,0 +1,13 @@ +package com.halilibo.richtext.markdown + +import androidx.compose.foundation.text.BasicText +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect + +@Composable +internal actual fun HtmlBlock(content: String) { + SideEffect { + println("Html blocks are rendered literally in Compose Desktop!") + } + BasicText(content) +} diff --git a/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt b/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt new file mode 100644 index 00000000..e33457d3 --- /dev/null +++ b/richtext-commonmark/src/jvmMain/kotlin/com/halilibo/richtext/markdown/RemoteImage.kt @@ -0,0 +1,61 @@ +package com.halilibo.richtext.markdown + +import androidx.compose.foundation.Image +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.jetbrains.skija.Image.makeFromEncoded +import java.awt.image.BufferedImage +import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.net.HttpURLConnection +import java.net.URL +import javax.imageio.ImageIO + +@Composable +internal actual fun RemoteImage( + url: String, + contentDescription: String?, + modifier: Modifier, + contentScale: ContentScale +) { + val image by produceState(null, url) { + loadFullImage(url)?.let { + value = makeFromEncoded(toByteArray(it)).asImageBitmap() + } + } + + if (image != null) { + Image( + bitmap = image!!, + contentDescription = contentDescription, + modifier = modifier, + contentScale = contentScale + ) + } +} + +private fun toByteArray(bitmap: BufferedImage): ByteArray { + val baos = ByteArrayOutputStream() + ImageIO.write(bitmap, "png", baos) + return baos.toByteArray() +} + +private suspend fun loadFullImage(source: String): BufferedImage? = withContext(Dispatchers.IO) { + runCatching { + val url = URL(source) + val connection: HttpURLConnection = url.openConnection() as HttpURLConnection + connection.connectTimeout = 5000 + connection.connect() + + val input: InputStream = connection.inputStream + val bitmap: BufferedImage? = ImageIO.read(input) + bitmap + }.getOrNull() +} diff --git a/richtext-commonmark/src/main/AndroidManifest.xml b/richtext-commonmark/src/main/AndroidManifest.xml deleted file mode 100644 index e52112c7..00000000 --- a/richtext-commonmark/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/richtext-ui-material/api/richtext-ui-material.api b/richtext-ui-material/api/richtext-ui-material.api deleted file mode 100644 index 0ce725b7..00000000 --- a/richtext-ui-material/api/richtext-ui-material.api +++ /dev/null @@ -1,21 +0,0 @@ -public final class com/zachklipp/richtext/ui/material/BuildConfig { - public static final field BUILD_TYPE Ljava/lang/String; - public static final field DEBUG Z - public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; - public fun ()V -} - -public final class com/zachklipp/richtext/ui/material/ComposableSingletons$MaterialRichTextKt { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/material/ComposableSingletons$MaterialRichTextKt; - public static field lambda-1 Lkotlin/jvm/functions/Function4; - public static field lambda-2 Lkotlin/jvm/functions/Function4; - public fun ()V - public final fun getLambda-1$richtext_ui_material_release ()Lkotlin/jvm/functions/Function4; - public final fun getLambda-2$richtext_ui_material_release ()Lkotlin/jvm/functions/Function4; -} - -public final class com/zachklipp/richtext/ui/material/MaterialRichTextKt { - public static final fun MaterialRichText (Landroidx/compose/ui/Modifier;Lcom/zachklipp/richtext/ui/RichTextStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V - public static final fun SetupMaterialRichText (Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V -} - diff --git a/richtext-ui-material/build.gradle b/richtext-ui-material/build.gradle deleted file mode 100644 index 227ede60..00000000 --- a/richtext-ui-material/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id('org.jetbrains.dokka') -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply from: rootProject.file('gradle/maven-publish.gradle') - -android rootProject.ext.defaultAndroidConfig - -dependencies { - compileOnly deps.compose.tooling - - api project(":richtext-ui") - implementation deps.compose.material -} diff --git a/richtext-ui-material/build.gradle.kts b/richtext-ui-material/build.gradle.kts new file mode 100644 index 00000000..6e0791d5 --- /dev/null +++ b/richtext-ui-material/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + id("richtext-kmp-library") + id("org.jetbrains.compose") version "1.0.0-alpha3" + id("org.jetbrains.dokka") +} + +repositories { + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") +} + +kotlin { + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material) + implementation(project(":richtext-ui")) + } + } + val commonTest by getting + + val androidMain by getting + val jvmMain by getting + } +} diff --git a/richtext-ui-material/consumer-rules.pro b/richtext-ui-material/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/richtext-ui-material/gradle.properties b/richtext-ui-material/gradle.properties index b970d057..28a01fa9 100644 --- a/richtext-ui-material/gradle.properties +++ b/richtext-ui-material/gradle.properties @@ -1,4 +1,4 @@ POM_ARTIFACT_ID=richtext-ui-material POM_NAME=Compose Richtext UI Material POM_DESCRIPTION=An extension library for RichText UI to easily bind with Material apps. -POM_PACKAGING=aar +POM_PACKAGING=aar \ No newline at end of file diff --git a/richtext-ui-material/proguard-rules.pro b/richtext-ui-material/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/richtext-ui-material/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/richtext-ui-material/src/androidMain/AndroidManifest.xml b/richtext-ui-material/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..14516796 --- /dev/null +++ b/richtext-ui-material/src/androidMain/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/richtext-ui-material/src/main/java/com/zachklipp/richtext/ui/material/MaterialRichText.kt b/richtext-ui-material/src/commonMain/kotlin/com/halilibo/richtext/ui/material/MaterialRichText.kt similarity index 90% rename from richtext-ui-material/src/main/java/com/zachklipp/richtext/ui/material/MaterialRichText.kt rename to richtext-ui-material/src/commonMain/kotlin/com/halilibo/richtext/ui/material/MaterialRichText.kt index 8e91c8ca..5168f70a 100644 --- a/richtext-ui-material/src/main/java/com/zachklipp/richtext/ui/material/MaterialRichText.kt +++ b/richtext-ui-material/src/commonMain/kotlin/com/halilibo/richtext/ui/material/MaterialRichText.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui.material +package com.halilibo.richtext.ui.material import androidx.compose.material.LocalContentColor import androidx.compose.material.LocalTextStyle @@ -7,10 +7,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.Modifier -import com.zachklipp.richtext.ui.RichText -import com.zachklipp.richtext.ui.RichTextScope -import com.zachklipp.richtext.ui.RichTextStyle -import com.zachklipp.richtext.ui.RichTextThemeIntegration +import com.halilibo.richtext.ui.RichText +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.RichTextStyle +import com.halilibo.richtext.ui.RichTextThemeIntegration /** * RichText implementation that integrates with Material design. diff --git a/richtext-ui-material/src/main/AndroidManifest.xml b/richtext-ui-material/src/main/AndroidManifest.xml deleted file mode 100644 index eb92abdf..00000000 --- a/richtext-ui-material/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/richtext-ui/api/richtext-ui.api b/richtext-ui/api/richtext-ui.api deleted file mode 100644 index eb5d8b72..00000000 --- a/richtext-ui/api/richtext-ui.api +++ /dev/null @@ -1,381 +0,0 @@ -public abstract interface class com/zachklipp/richtext/ui/BlockQuoteGutter { - public abstract fun gutterModifier (Lcom/zachklipp/richtext/ui/RichTextScope;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier; -} - -public final class com/zachklipp/richtext/ui/BlockQuoteGutter$BarGutter : com/zachklipp/richtext/ui/BlockQuoteGutter { - public synthetic fun (JJJLkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (JJJLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-XSAIIZE ()J - public final fun component2-XSAIIZE ()J - public final fun component3-XSAIIZE ()J - public final fun component4 ()Lkotlin/jvm/functions/Function1; - public final fun copy-mDbLjjM (JJJLkotlin/jvm/functions/Function1;)Lcom/zachklipp/richtext/ui/BlockQuoteGutter$BarGutter; - public static synthetic fun copy-mDbLjjM$default (Lcom/zachklipp/richtext/ui/BlockQuoteGutter$BarGutter;JJJLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/BlockQuoteGutter$BarGutter; - public fun equals (Ljava/lang/Object;)Z - public final fun getBarWidth-XSAIIZE ()J - public final fun getColor ()Lkotlin/jvm/functions/Function1; - public final fun getEndMargin-XSAIIZE ()J - public final fun getStartMargin-XSAIIZE ()J - public fun gutterModifier (Lcom/zachklipp/richtext/ui/RichTextScope;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/BlockQuoteKt { - public static final fun BlockQuote (Lcom/zachklipp/richtext/ui/RichTextScope;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/BuildConfig { - public static final field BUILD_TYPE Ljava/lang/String; - public static final field DEBUG Z - public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; - public fun ()V -} - -public final class com/zachklipp/richtext/ui/CodeBlockKt { - public static final fun CodeBlock (Lcom/zachklipp/richtext/ui/RichTextScope;Ljava/lang/String;Landroidx/compose/runtime/Composer;I)V - public static final fun CodeBlock (Lcom/zachklipp/richtext/ui/RichTextScope;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/CodeBlockStyle { - public static final field Companion Lcom/zachklipp/richtext/ui/CodeBlockStyle$Companion; - public synthetic fun (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/unit/TextUnit;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Landroidx/compose/ui/text/TextStyle; - public final fun component2-QN2ZGVo ()Landroidx/compose/ui/graphics/Color; - public final fun component3-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun copy-pvDJ3Jw (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/unit/TextUnit;)Lcom/zachklipp/richtext/ui/CodeBlockStyle; - public static synthetic fun copy-pvDJ3Jw$default (Lcom/zachklipp/richtext/ui/CodeBlockStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/graphics/Color;Landroidx/compose/ui/unit/TextUnit;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/CodeBlockStyle; - public fun equals (Ljava/lang/Object;)Z - public final fun getBackground-QN2ZGVo ()Landroidx/compose/ui/graphics/Color; - public final fun getPadding-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun getTextStyle ()Landroidx/compose/ui/text/TextStyle; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/CodeBlockStyle$Companion { - public final fun getDefault ()Lcom/zachklipp/richtext/ui/CodeBlockStyle; -} - -public final class com/zachklipp/richtext/ui/ComposableSingletons$BlockQuoteKt { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/ComposableSingletons$BlockQuoteKt; - public static field lambda-1 Lkotlin/jvm/functions/Function3; - public static field lambda-2 Lkotlin/jvm/functions/Function3; - public fun ()V - public final fun getLambda-1$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-2$richtext_ui_release ()Lkotlin/jvm/functions/Function3; -} - -public final class com/zachklipp/richtext/ui/ComposableSingletons$FormattedListKt { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/ComposableSingletons$FormattedListKt; - public static field lambda-1 Lkotlin/jvm/functions/Function4; - public fun ()V - public final fun getLambda-1$richtext_ui_release ()Lkotlin/jvm/functions/Function4; -} - -public final class com/zachklipp/richtext/ui/ComposableSingletons$RichTextThemeIntegrationKt { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/ComposableSingletons$RichTextThemeIntegrationKt; - public static field lambda-1 Lkotlin/jvm/functions/Function4; - public static field lambda-2 Lkotlin/jvm/functions/Function4; - public fun ()V - public final fun getLambda-1$richtext_ui_release ()Lkotlin/jvm/functions/Function4; - public final fun getLambda-2$richtext_ui_release ()Lkotlin/jvm/functions/Function4; -} - -public final class com/zachklipp/richtext/ui/ComposableSingletons$TableKt { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/ComposableSingletons$TableKt; - public static field lambda-1 Lkotlin/jvm/functions/Function3; - public static field lambda-2 Lkotlin/jvm/functions/Function3; - public static field lambda-3 Lkotlin/jvm/functions/Function3; - public static field lambda-4 Lkotlin/jvm/functions/Function3; - public static field lambda-5 Lkotlin/jvm/functions/Function3; - public static field lambda-6 Lkotlin/jvm/functions/Function3; - public static field lambda-7 Lkotlin/jvm/functions/Function3; - public fun ()V - public final fun getLambda-1$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-2$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-3$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-4$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-5$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-6$richtext_ui_release ()Lkotlin/jvm/functions/Function3; - public final fun getLambda-7$richtext_ui_release ()Lkotlin/jvm/functions/Function3; -} - -public final class com/zachklipp/richtext/ui/FormattedListKt { - public static final fun FormattedList (Lcom/zachklipp/richtext/ui/RichTextScope;Lcom/zachklipp/richtext/ui/ListType;Ljava/util/List;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;I)V - public static final fun FormattedList (Lcom/zachklipp/richtext/ui/RichTextScope;Lcom/zachklipp/richtext/ui/ListType;[Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V - public static final fun painterUnorderedMarkers ([Landroidx/compose/ui/graphics/painter/Painter;)Lcom/zachklipp/richtext/ui/UnorderedMarkers; - public static final fun textOrderedMarkers (Lcom/zachklipp/richtext/ui/RichTextScope;[Lkotlin/jvm/functions/Function1;)Lcom/zachklipp/richtext/ui/OrderedMarkers; - public static final fun textUnorderedMarkers (Lcom/zachklipp/richtext/ui/RichTextScope;[Ljava/lang/String;)Lcom/zachklipp/richtext/ui/UnorderedMarkers; -} - -public final class com/zachklipp/richtext/ui/HeadingKt { - public static final fun Heading (Lcom/zachklipp/richtext/ui/RichTextScope;ILjava/lang/String;Landroidx/compose/runtime/Composer;I)V - public static final fun Heading (Lcom/zachklipp/richtext/ui/RichTextScope;ILkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/HorizontalRuleKt { - public static final fun HorizontalRule (Lcom/zachklipp/richtext/ui/RichTextScope;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/ListStyle { - public static final field Companion Lcom/zachklipp/richtext/ui/ListStyle$Companion; - public synthetic fun (Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun component2-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun component3 ()Lkotlin/jvm/functions/Function1; - public final fun component4 ()Lkotlin/jvm/functions/Function1; - public final fun copy-iXsHpI0 (Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcom/zachklipp/richtext/ui/ListStyle; - public static synthetic fun copy-iXsHpI0$default (Lcom/zachklipp/richtext/ui/ListStyle;Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/ListStyle; - public fun equals (Ljava/lang/Object;)Z - public final fun getContentsIndent-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun getMarkerIndent-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun getOrderedMarkers ()Lkotlin/jvm/functions/Function1; - public final fun getUnorderedMarkers ()Lkotlin/jvm/functions/Function1; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/ListStyle$Companion { - public final fun getDefault ()Lcom/zachklipp/richtext/ui/ListStyle; -} - -public final class com/zachklipp/richtext/ui/ListType : java/lang/Enum { - public static final field Ordered Lcom/zachklipp/richtext/ui/ListType; - public static final field Unordered Lcom/zachklipp/richtext/ui/ListType; - public static fun valueOf (Ljava/lang/String;)Lcom/zachklipp/richtext/ui/ListType; - public static fun values ()[Lcom/zachklipp/richtext/ui/ListType; -} - -public abstract interface class com/zachklipp/richtext/ui/OrderedMarkers { - public static final field Companion Lcom/zachklipp/richtext/ui/OrderedMarkers$Companion; - public abstract fun drawMarker (IILandroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/OrderedMarkers$Companion { - public final fun invoke (Lkotlin/jvm/functions/Function4;)Lcom/zachklipp/richtext/ui/OrderedMarkers; -} - -public final class com/zachklipp/richtext/ui/RichTextKt { - public static final fun RichText (Landroidx/compose/ui/Modifier;Lcom/zachklipp/richtext/ui/RichTextStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V -} - -public final class com/zachklipp/richtext/ui/RichTextScope { - public static final field INSTANCE Lcom/zachklipp/richtext/ui/RichTextScope; -} - -public final class com/zachklipp/richtext/ui/RichTextStyle { - public static final field Companion Lcom/zachklipp/richtext/ui/RichTextStyle$Companion; - public synthetic fun (Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function2;Lcom/zachklipp/richtext/ui/ListStyle;Lcom/zachklipp/richtext/ui/BlockQuoteGutter;Lcom/zachklipp/richtext/ui/CodeBlockStyle;Lcom/zachklipp/richtext/ui/TableStyle;Lcom/zachklipp/richtext/ui/string/RichTextStringStyle;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function2;Lcom/zachklipp/richtext/ui/ListStyle;Lcom/zachklipp/richtext/ui/BlockQuoteGutter;Lcom/zachklipp/richtext/ui/CodeBlockStyle;Lcom/zachklipp/richtext/ui/TableStyle;Lcom/zachklipp/richtext/ui/string/RichTextStringStyle;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun component2 ()Lkotlin/jvm/functions/Function2; - public final fun component3 ()Lcom/zachklipp/richtext/ui/ListStyle; - public final fun component4 ()Lcom/zachklipp/richtext/ui/BlockQuoteGutter; - public final fun component5 ()Lcom/zachklipp/richtext/ui/CodeBlockStyle; - public final fun component6 ()Lcom/zachklipp/richtext/ui/TableStyle; - public final fun component7 ()Lcom/zachklipp/richtext/ui/string/RichTextStringStyle; - public final fun copy-rSDT1DU (Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function2;Lcom/zachklipp/richtext/ui/ListStyle;Lcom/zachklipp/richtext/ui/BlockQuoteGutter;Lcom/zachklipp/richtext/ui/CodeBlockStyle;Lcom/zachklipp/richtext/ui/TableStyle;Lcom/zachklipp/richtext/ui/string/RichTextStringStyle;)Lcom/zachklipp/richtext/ui/RichTextStyle; - public static synthetic fun copy-rSDT1DU$default (Lcom/zachklipp/richtext/ui/RichTextStyle;Landroidx/compose/ui/unit/TextUnit;Lkotlin/jvm/functions/Function2;Lcom/zachklipp/richtext/ui/ListStyle;Lcom/zachklipp/richtext/ui/BlockQuoteGutter;Lcom/zachklipp/richtext/ui/CodeBlockStyle;Lcom/zachklipp/richtext/ui/TableStyle;Lcom/zachklipp/richtext/ui/string/RichTextStringStyle;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/RichTextStyle; - public fun equals (Ljava/lang/Object;)Z - public final fun getBlockQuoteGutter ()Lcom/zachklipp/richtext/ui/BlockQuoteGutter; - public final fun getCodeBlockStyle ()Lcom/zachklipp/richtext/ui/CodeBlockStyle; - public final fun getHeadingStyle ()Lkotlin/jvm/functions/Function2; - public final fun getListStyle ()Lcom/zachklipp/richtext/ui/ListStyle; - public final fun getParagraphSpacing-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun getStringStyle ()Lcom/zachklipp/richtext/ui/string/RichTextStringStyle; - public final fun getTableStyle ()Lcom/zachklipp/richtext/ui/TableStyle; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/RichTextStyle$Companion { - public final fun getDefault ()Lcom/zachklipp/richtext/ui/RichTextStyle; -} - -public final class com/zachklipp/richtext/ui/RichTextStyleKt { - public static final fun WithStyle (Lcom/zachklipp/richtext/ui/RichTextScope;Lcom/zachklipp/richtext/ui/RichTextStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V - public static final fun getCurrentRichTextStyle (Lcom/zachklipp/richtext/ui/RichTextScope;Landroidx/compose/runtime/Composer;I)Lcom/zachklipp/richtext/ui/RichTextStyle; - public static final fun merge (Lcom/zachklipp/richtext/ui/RichTextStyle;Lcom/zachklipp/richtext/ui/RichTextStyle;)Lcom/zachklipp/richtext/ui/RichTextStyle; - public static final fun resolveDefaults (Lcom/zachklipp/richtext/ui/RichTextStyle;)Lcom/zachklipp/richtext/ui/RichTextStyle; -} - -public abstract interface class com/zachklipp/richtext/ui/RichTextTableCellScope { - public abstract fun cell (Lkotlin/jvm/functions/Function3;)V -} - -public abstract interface class com/zachklipp/richtext/ui/RichTextTableRowScope { - public abstract fun row (Lkotlin/jvm/functions/Function1;)V -} - -public final class com/zachklipp/richtext/ui/RichTextThemeIntegrationKt { - public static final fun RichTextThemeIntegration (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V -} - -public final class com/zachklipp/richtext/ui/TableKt { - public static final fun Table (Lcom/zachklipp/richtext/ui/RichTextScope;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;II)V -} - -public final class com/zachklipp/richtext/ui/TableStyle { - public static final field Companion Lcom/zachklipp/richtext/ui/TableStyle$Companion; - public synthetic fun (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/graphics/Color;Ljava/lang/Float;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/graphics/Color;Ljava/lang/Float;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Landroidx/compose/ui/text/TextStyle; - public final fun component2-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun component3-QN2ZGVo ()Landroidx/compose/ui/graphics/Color; - public final fun component4 ()Ljava/lang/Float; - public final fun copy-gowntrk (Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/graphics/Color;Ljava/lang/Float;)Lcom/zachklipp/richtext/ui/TableStyle; - public static synthetic fun copy-gowntrk$default (Lcom/zachklipp/richtext/ui/TableStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/unit/TextUnit;Landroidx/compose/ui/graphics/Color;Ljava/lang/Float;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/TableStyle; - public fun equals (Ljava/lang/Object;)Z - public final fun getBorderColor-QN2ZGVo ()Landroidx/compose/ui/graphics/Color; - public final fun getBorderStrokeWidth ()Ljava/lang/Float; - public final fun getCellPadding-U3a4LBI ()Landroidx/compose/ui/unit/TextUnit; - public final fun getHeaderTextStyle ()Landroidx/compose/ui/text/TextStyle; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/TableStyle$Companion { - public final fun getDefault ()Lcom/zachklipp/richtext/ui/TableStyle; -} - -public abstract interface class com/zachklipp/richtext/ui/UnorderedMarkers { - public static final field Companion Lcom/zachklipp/richtext/ui/UnorderedMarkers$Companion; - public abstract fun drawMarker (ILandroidx/compose/runtime/Composer;I)V -} - -public final class com/zachklipp/richtext/ui/UnorderedMarkers$Companion { - public final fun invoke (Lkotlin/jvm/functions/Function3;)Lcom/zachklipp/richtext/ui/UnorderedMarkers; -} - -public final class com/zachklipp/richtext/ui/string/InlineContent { - public static final field $stable I - public synthetic fun (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/functions/Function4;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/functions/Function4;Lkotlin/jvm/internal/DefaultConstructorMarker;)V -} - -public final class com/zachklipp/richtext/ui/string/RichTextString { - public final fun copy (Landroidx/compose/ui/text/AnnotatedString;Ljava/util/Map;)Lcom/zachklipp/richtext/ui/string/RichTextString; - public static synthetic fun copy$default (Lcom/zachklipp/richtext/ui/string/RichTextString;Landroidx/compose/ui/text/AnnotatedString;Ljava/util/Map;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/string/RichTextString; - public fun equals (Ljava/lang/Object;)Z - public final fun getText ()Ljava/lang/String; - public fun hashCode ()I - public final fun plus (Lcom/zachklipp/richtext/ui/string/RichTextString;)Lcom/zachklipp/richtext/ui/string/RichTextString; - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Builder { - public static final field $stable I - public fun ()V - public fun (I)V - public synthetic fun (IILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun addFormat (Lcom/zachklipp/richtext/ui/string/RichTextString$Format;II)V - public final fun append (Lcom/zachklipp/richtext/ui/string/RichTextString;)V - public final fun append (Ljava/lang/String;)V - public final fun appendInlineContent (Ljava/lang/String;Lcom/zachklipp/richtext/ui/string/InlineContent;)V - public static synthetic fun appendInlineContent$default (Lcom/zachklipp/richtext/ui/string/RichTextString$Builder;Ljava/lang/String;Lcom/zachklipp/richtext/ui/string/InlineContent;ILjava/lang/Object;)V - public final fun pop ()V - public final fun pop (I)V - public final fun pushFormat (Lcom/zachklipp/richtext/ui/string/RichTextString$Format;)I - public final fun toRichTextString ()Lcom/zachklipp/richtext/ui/string/RichTextString; - public final fun withAnnotatedString (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public abstract class com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field Companion Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Companion; - public synthetic fun (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Bold : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Bold; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Code : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Code; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Italic : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Italic; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Link : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field Companion Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Link$Companion; - public fun (Lkotlin/jvm/functions/Function0;)V - public final fun component1 ()Lkotlin/jvm/functions/Function0; - public final fun copy (Lkotlin/jvm/functions/Function0;)Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Link; - public static synthetic fun copy$default (Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Link;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Link; - public fun equals (Ljava/lang/Object;)Z - public final fun getOnClick ()Lkotlin/jvm/functions/Function0; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Strikethrough : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Strikethrough; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Subscript : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Subscript; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Superscript : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Superscript; -} - -public final class com/zachklipp/richtext/ui/string/RichTextString$Format$Underline : com/zachklipp/richtext/ui/string/RichTextString$Format { - public static final field $stable I - public static final field INSTANCE Lcom/zachklipp/richtext/ui/string/RichTextString$Format$Underline; -} - -public final class com/zachklipp/richtext/ui/string/RichTextStringKt { - public static final fun richTextString (Lkotlin/jvm/functions/Function1;)Lcom/zachklipp/richtext/ui/string/RichTextString; - public static final fun withFormat (Lcom/zachklipp/richtext/ui/string/RichTextString$Builder;Lcom/zachklipp/richtext/ui/string/RichTextString$Format;Lkotlin/jvm/functions/Function1;)V -} - -public final class com/zachklipp/richtext/ui/string/RichTextStringStyle { - public static final field Companion Lcom/zachklipp/richtext/ui/string/RichTextStringStyle$Companion; - public fun ()V - public fun (Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;)V - public synthetic fun (Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component2 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component3 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component4 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component5 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component6 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component7 ()Landroidx/compose/ui/text/SpanStyle; - public final fun component8 ()Landroidx/compose/ui/text/SpanStyle; - public final fun copy (Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;)Lcom/zachklipp/richtext/ui/string/RichTextStringStyle; - public static synthetic fun copy$default (Lcom/zachklipp/richtext/ui/string/RichTextStringStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;Landroidx/compose/ui/text/SpanStyle;ILjava/lang/Object;)Lcom/zachklipp/richtext/ui/string/RichTextStringStyle; - public fun equals (Ljava/lang/Object;)Z - public final fun getBoldStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getCodeStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getItalicStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getLinkStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getStrikethroughStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getSubscriptStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getSuperscriptStyle ()Landroidx/compose/ui/text/SpanStyle; - public final fun getUnderlineStyle ()Landroidx/compose/ui/text/SpanStyle; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/zachklipp/richtext/ui/string/RichTextStringStyle$Companion { - public final fun getDefault ()Lcom/zachklipp/richtext/ui/string/RichTextStringStyle; -} - -public final class com/zachklipp/richtext/ui/string/TextKt { - public static final fun Text-7zs97cc (Lcom/zachklipp/richtext/ui/RichTextScope;Lcom/zachklipp/richtext/ui/string/RichTextString;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;ZIILandroidx/compose/runtime/Composer;II)V -} - diff --git a/richtext-ui/build.gradle b/richtext-ui/build.gradle deleted file mode 100644 index 0a2f0ec8..00000000 --- a/richtext-ui/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -plugins { - id('org.jetbrains.dokka') -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply from: rootProject.file('gradle/maven-publish.gradle') - -android rootProject.ext.defaultAndroidConfig - -dependencies { - compileOnly deps.compose.activity - compileOnly deps.compose.tooling - - api deps.androidx.annotations - api deps.compose.foundation -} diff --git a/richtext-ui/build.gradle.kts b/richtext-ui/build.gradle.kts new file mode 100644 index 00000000..a949881a --- /dev/null +++ b/richtext-ui/build.gradle.kts @@ -0,0 +1,32 @@ +plugins { + id("richtext-kmp-library") + id("org.jetbrains.compose") version "1.0.0-alpha3" + id("org.jetbrains.dokka") +} + +repositories { + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") +} + +kotlin { + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + } + } + val commonTest by getting + + val androidMain by getting { + kotlin.srcDir("src/commonJvmAndroid/kotlin") + } + val jvmMain by getting { + kotlin.srcDir("src/commonJvmAndroid/kotlin") + dependencies { + // requires installing https://plugins.jetbrains.com/plugin/16541-compose-multiplatform-ide-support + implementation(Compose.desktopPreview) + } + } + } +} diff --git a/richtext-ui/consumer-rules.pro b/richtext-ui/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/richtext-ui/gradle.properties b/richtext-ui/gradle.properties index cea3b3a5..38a0614a 100644 --- a/richtext-ui/gradle.properties +++ b/richtext-ui/gradle.properties @@ -1,4 +1,4 @@ POM_ARTIFACT_ID=richtext-ui POM_NAME=Compose Richtext UI POM_DESCRIPTION=A library for rendering high-level text formatting in Compose. -POM_PACKAGING=aar +POM_PACKAGING=aar \ No newline at end of file diff --git a/richtext-ui/proguard-rules.pro b/richtext-ui/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/richtext-ui/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/richtext-ui/src/main/AndroidManifest.xml b/richtext-ui/src/androidMain/AndroidManifest.xml similarity index 100% rename from richtext-ui/src/main/AndroidManifest.xml rename to richtext-ui/src/androidMain/AndroidManifest.xml diff --git a/richtext-ui/src/commonJvmAndroid/kotlin/com/halilibo/richtext/ui/util/UUID.kt b/richtext-ui/src/commonJvmAndroid/kotlin/com/halilibo/richtext/ui/util/UUID.kt new file mode 100644 index 00000000..ddfbf000 --- /dev/null +++ b/richtext-ui/src/commonJvmAndroid/kotlin/com/halilibo/richtext/ui/util/UUID.kt @@ -0,0 +1,7 @@ +package com.halilibo.richtext.ui.util + +import java.util.UUID + +internal actual fun randomUUID(): String { + return UUID.randomUUID().toString() +} \ No newline at end of file diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/BlockQuote.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/BlockQuote.kt similarity index 80% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/BlockQuote.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/BlockQuote.kt index ef1521c3..8cf6a26e 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/BlockQuote.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/BlockQuote.kt @@ -1,6 +1,6 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -8,19 +8,17 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.offset import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.BlockQuoteGutter.BarGutter +import com.halilibo.richtext.ui.BlockQuoteGutter.BarGutter internal val DefaultBlockQuoteGutter = BarGutter() @@ -104,28 +102,3 @@ public interface BlockQuoteGutter { } } } - -@Preview @Composable private fun BlockQuotePreviewOnWhite() { - BlockQuotePreview(backgroundColor = Color.White, contentColor = Color.Black) -} - -@Preview @Composable private fun BlockQuotePreviewOnBlack() { - BlockQuotePreview(backgroundColor = Color.Black, contentColor = Color.White) -} - -@Composable private fun BlockQuotePreview( - backgroundColor: Color, - contentColor: Color -) { - CompositionLocalProvider(LocalInternalContentColor provides contentColor) { - Box(Modifier.background(backgroundColor)) { - RichTextScope.BlockQuote { - Text("Some text.") - Text("Another paragraph.") - BlockQuote { - Text("Nested block quote.") - } - } - } - } -} diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/CodeBlock.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/CodeBlock.kt similarity index 75% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/CodeBlock.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/CodeBlock.kt index 2cfe3722..c2fef401 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/CodeBlock.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/CodeBlock.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -11,7 +11,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -78,33 +77,3 @@ internal fun CodeBlockStyle.resolveDefaults() = CodeBlockStyle( } } } - -@Preview @Composable -private fun CodeBlockPreviewOnWhite() { - CodeBlockPreview(backgroundColor = Color.White, contentColor = Color.Black) -} - -@Preview @Composable -private fun CodeBlockPreviewOnBlack() { - CodeBlockPreview(backgroundColor = Color.Black, contentColor = Color.White) -} - -@Composable -private fun CodeBlockPreview( - backgroundColor: Color, - contentColor: Color -) { - CompositionLocalProvider(LocalInternalContentColor provides contentColor) { - Box(modifier = Modifier.background(color = backgroundColor)) { - Box(modifier = Modifier.padding(24.dp)) { - RichTextScope.CodeBlock( - """ - data class Hello( - val name: String - ) - """.trimIndent() - ) - } - } - } -} diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/FormattedList.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/FormattedList.kt similarity index 83% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/FormattedList.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/FormattedList.kt index 06c2e387..374bc2f9 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/FormattedList.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/FormattedList.kt @@ -1,6 +1,6 @@ @file:Suppress("ComposableNaming") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -19,14 +19,13 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.ListType.Ordered -import com.zachklipp.richtext.ui.ListType.Unordered +import com.halilibo.richtext.ui.ListType.Ordered +import com.halilibo.richtext.ui.ListType.Unordered import kotlin.math.max public enum class ListType { @@ -296,62 +295,3 @@ private val LocalListLevel = compositionLocalOf { 0 } } } } - -@Preview(heightDp = 400) -@Composable private fun UnorderedListPreview() { - ListPreview(listType = Unordered, layoutDirection = LayoutDirection.Ltr) -} - -@Preview(heightDp = 400) -@Composable private fun UnorderedListPreviewRtl() { - ListPreview(listType = Unordered, layoutDirection = LayoutDirection.Rtl) -} - -@Preview(heightDp = 400) -@Composable private fun OrderedListPreview() { - ListPreview(listType = Ordered, layoutDirection = LayoutDirection.Ltr) -} - -@Preview(heightDp = 400) -@Composable private fun OrderedListPreviewRtl() { - ListPreview(listType = Ordered, layoutDirection = LayoutDirection.Rtl) -} - -@Composable private fun ListPreview( - listType: ListType, - layoutDirection: LayoutDirection -) { - CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { - Box(Modifier.background(color = Color.White)) { - RichTextScope.FormattedList( - listType = listType, - items = listOf( - "Foo", - "Bar", - "Baz", - "Foo", - "Bar", - "Baz", - "Foo", - "Bar", - "Foo\nBar\nBaz", - "Foo" - ).withIndex() - .toList() - ) { (index, text) -> - Text(text) - if (index == 0) { - FormattedList(listType, @Composable { - Text("indented $text") - FormattedList(listType, @Composable { - Text("indented $text") - FormattedList(listType, @Composable { - Text("indented $text") - }) - }) - }) - } - } - } - } -} diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/Heading.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Heading.kt similarity index 78% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/Heading.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Heading.kt index 27ae3145..65812220 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/Heading.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Heading.kt @@ -1,8 +1,7 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui -import androidx.annotation.IntRange import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -16,7 +15,6 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontStyle.Companion.Italic import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.resolveDefaults -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp /** @@ -68,7 +66,7 @@ internal val DefaultHeadingStyle: HeadingStyle = { level, textStyle -> * @param level The non-negative rank of the header, with 0 being the most important. */ @Composable public fun RichTextScope.Heading( - @IntRange(from = 0L, to = Long.MAX_VALUE) level: Int, + level: Int, text: String ) { Heading(level) { @@ -100,26 +98,3 @@ internal val DefaultHeadingStyle: HeadingStyle = { level, textStyle -> children() } } - -@Preview @Composable private fun HeadingPreviewOnWhite() { - HeadingPreview(backgroundColor = Color.White, contentColor = Color.Black) -} - -@Preview @Composable private fun HeadingPreviewOnBlack() { - HeadingPreview(backgroundColor = Color.Black, contentColor = Color.White) -} - -@Composable private fun HeadingPreview( - backgroundColor: Color, - contentColor: Color -) { - CompositionLocalProvider(LocalInternalContentColor provides contentColor) { - Box(Modifier.background(color = backgroundColor)) { - Column { - for (level in 0 until 10) { - RichTextScope.Heading(level, "Heading ${level + 1}") - } - } - } - } -} diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/HorizontalRule.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/HorizontalRule.kt similarity index 96% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/HorizontalRule.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/HorizontalRule.kt index 0820ee01..f1c249b5 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/HorizontalRule.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/HorizontalRule.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichText.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichText.kt similarity index 96% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichText.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichText.kt index 7d4825d1..68b7d9e5 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichText.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichText.kt @@ -1,6 +1,6 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Column diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextLocals.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextLocals.kt similarity index 97% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextLocals.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextLocals.kt index ddd78369..07c6c2ae 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextLocals.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextLocals.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.text.BasicText @@ -15,7 +15,6 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow -import com.zachklipp.richtext.ui.string.RichTextString /** * Carries the text style in Composition tree. [Heading], [CodeBlock], diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextScope.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextScope.kt similarity index 94% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextScope.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextScope.kt index 4521a05b..681abc87 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextScope.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextScope.kt @@ -1,6 +1,6 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocal diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextStyle.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextStyle.kt similarity index 66% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextStyle.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextStyle.kt index 432b188a..39baa4ee 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextStyle.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextStyle.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -6,7 +6,9 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.string.RichTextStringStyle +import com.halilibo.richtext.ui.BlockQuoteGutter +import com.halilibo.richtext.ui.DefaultBlockQuoteGutter +import com.halilibo.richtext.ui.string.RichTextStringStyle internal val LocalRichTextStyle = compositionLocalOf { RichTextStyle.Default } internal val DefaultParagraphSpacing: TextUnit = 8.sp @@ -39,23 +41,23 @@ public data class RichTextStyle( } public fun RichTextStyle.merge(otherStyle: RichTextStyle?): RichTextStyle = RichTextStyle( - paragraphSpacing = otherStyle?.paragraphSpacing ?: paragraphSpacing, - headingStyle = otherStyle?.headingStyle ?: headingStyle, - listStyle = otherStyle?.listStyle ?: listStyle, - blockQuoteGutter = otherStyle?.blockQuoteGutter ?: blockQuoteGutter, - codeBlockStyle = otherStyle?.codeBlockStyle ?: codeBlockStyle, - tableStyle = otherStyle?.tableStyle ?: tableStyle, - stringStyle = stringStyle?.merge(otherStyle?.stringStyle) ?: otherStyle?.stringStyle + paragraphSpacing = otherStyle?.paragraphSpacing ?: paragraphSpacing, + headingStyle = otherStyle?.headingStyle ?: headingStyle, + listStyle = otherStyle?.listStyle ?: listStyle, + blockQuoteGutter = otherStyle?.blockQuoteGutter ?: blockQuoteGutter, + codeBlockStyle = otherStyle?.codeBlockStyle ?: codeBlockStyle, + tableStyle = otherStyle?.tableStyle ?: tableStyle, + stringStyle = stringStyle?.merge(otherStyle?.stringStyle) ?: otherStyle?.stringStyle ) public fun RichTextStyle.resolveDefaults(): RichTextStyle = RichTextStyle( - paragraphSpacing = paragraphSpacing ?: DefaultParagraphSpacing, - headingStyle = headingStyle ?: DefaultHeadingStyle, - listStyle = (listStyle ?: ListStyle.Default).resolveDefaults(), - blockQuoteGutter = blockQuoteGutter ?: DefaultBlockQuoteGutter, - codeBlockStyle = (codeBlockStyle ?: CodeBlockStyle.Default).resolveDefaults(), - tableStyle = (tableStyle ?: TableStyle.Default).resolveDefaults(), - stringStyle = (stringStyle ?: RichTextStringStyle.Default).resolveDefaults() + paragraphSpacing = paragraphSpacing ?: DefaultParagraphSpacing, + headingStyle = headingStyle ?: DefaultHeadingStyle, + listStyle = (listStyle ?: ListStyle.Default).resolveDefaults(), + blockQuoteGutter = blockQuoteGutter ?: DefaultBlockQuoteGutter, + codeBlockStyle = (codeBlockStyle ?: CodeBlockStyle.Default).resolveDefaults(), + tableStyle = (tableStyle ?: TableStyle.Default).resolveDefaults(), + stringStyle = (stringStyle ?: RichTextStringStyle.Default).resolveDefaults() ) /** diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextThemeIntegration.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeIntegration.kt similarity index 99% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextThemeIntegration.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeIntegration.kt index fa96fc14..bf4aeb7e 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/RichTextThemeIntegration.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/RichTextThemeIntegration.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/SimpleTableLayout.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/SimpleTableLayout.kt similarity index 99% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/SimpleTableLayout.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/SimpleTableLayout.kt index b7d3c807..7384ca5f 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/SimpleTableLayout.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/SimpleTableLayout.kt @@ -1,4 +1,4 @@ -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/Table.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Table.kt similarity index 87% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/Table.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Table.kt index 71b24d0f..e2c73ad7 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/Table.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/Table.kt @@ -1,6 +1,6 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry") -package com.zachklipp.richtext.ui +package com.halilibo.richtext.ui import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding @@ -16,10 +16,10 @@ import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.halilibo.richtext.ui.BlockQuote import kotlin.math.max /** @@ -188,44 +188,4 @@ private fun Modifier.drawTableBorders( borderStrokeWidth ) } -} - -@Preview -@Composable -private fun TablePreview() { - TablePreviewContents() -} - -@Preview(widthDp = 300) -@Composable -private fun TablePreviewFixedWidth() { - TablePreviewContents() -} - -@Composable -private fun TablePreviewContents(modifier: Modifier = Modifier) { - RichTextScope.Table( - modifier = modifier - .background(Color.White) - .padding(4.dp), - headerRow = { - cell { Text("Column 1") } - cell { Text("Column 2") } - } - ) { - row { - cell { Text("Hello") } - cell { - CodeBlock("Foo bar") - } - } - row { - cell { - BlockQuote { - Text("Stuff") - } - } - cell { Text("Hello world this is a really long line that is going to wrap hopefully") } - } - } -} +} \ No newline at end of file diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/InlineContent.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/InlineContent.kt similarity index 92% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/InlineContent.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/InlineContent.kt index c9bb56c2..7f9c35b2 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/InlineContent.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/InlineContent.kt @@ -1,9 +1,14 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry", "FunctionName") -package com.zachklipp.richtext.ui.string +package com.halilibo.richtext.ui.string import androidx.compose.foundation.text.InlineTextContent -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.structuralEqualityPolicy import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.Placeholder diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/RichTextString.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt similarity index 90% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/RichTextString.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt index d2590f3d..3dbc2c1a 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/RichTextString.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/RichTextString.kt @@ -1,6 +1,6 @@ @file:Suppress("RemoveEmptyParenthesesFromAnnotationEntry", "SuspiciousCollectionReassignment") -package com.zachklipp.richtext.ui.string +package com.halilibo.richtext.ui.string import androidx.compose.foundation.text.appendInlineContent import androidx.compose.runtime.Immutable @@ -14,19 +14,19 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.BaselineShift import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.sp -import com.zachklipp.richtext.ui.DefaultCodeBlockBackground -import com.zachklipp.richtext.ui.string.RichTextString.Builder -import com.zachklipp.richtext.ui.string.RichTextString.Format -import com.zachklipp.richtext.ui.string.RichTextString.Format.Bold -import com.zachklipp.richtext.ui.string.RichTextString.Format.Code -import com.zachklipp.richtext.ui.string.RichTextString.Format.Companion.FormatAnnotationScope -import com.zachklipp.richtext.ui.string.RichTextString.Format.Italic -import com.zachklipp.richtext.ui.string.RichTextString.Format.Link -import com.zachklipp.richtext.ui.string.RichTextString.Format.Strikethrough -import com.zachklipp.richtext.ui.string.RichTextString.Format.Subscript -import com.zachklipp.richtext.ui.string.RichTextString.Format.Superscript -import com.zachklipp.richtext.ui.string.RichTextString.Format.Underline -import java.util.UUID +import com.halilibo.richtext.ui.DefaultCodeBlockBackground +import com.halilibo.richtext.ui.string.RichTextString.Builder +import com.halilibo.richtext.ui.string.RichTextString.Format +import com.halilibo.richtext.ui.string.RichTextString.Format.Bold +import com.halilibo.richtext.ui.string.RichTextString.Format.Code +import com.halilibo.richtext.ui.string.RichTextString.Format.Companion.FormatAnnotationScope +import com.halilibo.richtext.ui.string.RichTextString.Format.Italic +import com.halilibo.richtext.ui.string.RichTextString.Format.Link +import com.halilibo.richtext.ui.string.RichTextString.Format.Strikethrough +import com.halilibo.richtext.ui.string.RichTextString.Format.Subscript +import com.halilibo.richtext.ui.string.RichTextString.Format.Superscript +import com.halilibo.richtext.ui.string.RichTextString.Format.Underline +import com.halilibo.richtext.ui.util.randomUUID import kotlin.LazyThreadSafetyMode.NONE /** Copied from inline content. */ @@ -242,13 +242,13 @@ public data class RichTextString internal constructor( internal fun registerTag(tags: MutableMap): String { simpleTag?.let { return it } - val uuid = UUID.randomUUID().toString() + val uuid = randomUUID() tags[uuid] = this return "format:$uuid" } internal companion object { - val FormatAnnotationScope = Format::class.java.name + val FormatAnnotationScope = Format::class.qualifiedName!! // For some reason, if this isn't lazy, Bold will always be null. Is Compose messing up static // initialization order? @@ -304,7 +304,7 @@ public data class RichTextString internal constructor( alternateText: String = REPLACEMENT_CHAR, content: InlineContent ) { - val tag = UUID.randomUUID().toString() + val tag = randomUUID() formatObjects["inline:$tag"] = content builder.appendInlineContent(tag, alternateText) } diff --git a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/Text.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/Text.kt similarity index 71% rename from richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/Text.kt rename to richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/Text.kt index d154f4d0..9c587eaf 100644 --- a/richtext-ui/src/main/java/com/zachklipp/richtext/ui/string/Text.kt +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/string/Text.kt @@ -1,18 +1,21 @@ -package com.zachklipp.richtext.ui.string +package com.halilibo.richtext.ui.string import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.style.TextOverflow -import com.zachklipp.richtext.ui.* -import com.zachklipp.richtext.ui.string.RichTextString.Format -import com.zachklipp.richtext.ui.string.RichTextString.Format.Link +import com.halilibo.richtext.ui.ClickableText +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.currentContentColor +import com.halilibo.richtext.ui.currentRichTextStyle +import com.halilibo.richtext.ui.string.RichTextString.Format /** * Renders a [RichTextString] as created with [richTextString]. * - * @sample com.zachklipp.richtext.ui.string.TextPreview + * @sample com.halilibo.richtext.ui.previews.TextPreview */ @Composable public fun RichTextScope.Text( @@ -48,7 +51,12 @@ public fun RichTextScope.Text( onClick = { offset -> annotated.getStringAnnotations(Format.FormatAnnotationScope, offset, offset) .asSequence() - .mapNotNull { Format.findTag(it.item, text.formatObjects) as? Link } + .mapNotNull { + Format.findTag( + it.item, + text.formatObjects + ) as? Format.Link + } .firstOrNull() ?.let { link -> link.onClick() } } diff --git a/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/UUID.kt b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/UUID.kt new file mode 100644 index 00000000..33b9dd2c --- /dev/null +++ b/richtext-ui/src/commonMain/kotlin/com/halilibo/richtext/ui/util/UUID.kt @@ -0,0 +1,3 @@ +package com.halilibo.richtext.ui.util + +internal expect fun randomUUID(): String \ No newline at end of file diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/BlockQuotePreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/BlockQuotePreview.kt new file mode 100644 index 00000000..aeab4929 --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/BlockQuotePreview.kt @@ -0,0 +1,41 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.halilibo.richtext.ui.BlockQuote +import com.halilibo.richtext.ui.LocalInternalContentColor +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.Text + +@Preview +@Composable +private fun BlockQuotePreviewOnWhite() { + BlockQuotePreview(backgroundColor = Color.White, contentColor = Color.Black) +} + +@Preview +@Composable private fun BlockQuotePreviewOnBlack() { + BlockQuotePreview(backgroundColor = Color.Black, contentColor = Color.White) +} + +@Composable private fun BlockQuotePreview( + backgroundColor: Color, + contentColor: Color +) { + CompositionLocalProvider(LocalInternalContentColor provides contentColor) { + Box(Modifier.background(backgroundColor)) { + RichTextScope.BlockQuote { + Text("Some text.") + Text("Another paragraph.") + BlockQuote { + Text("Nested block quote.") + } + } + } + } +} diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/CodeBlockPreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/CodeBlockPreview.kt new file mode 100644 index 00000000..1f8df1bc --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/CodeBlockPreview.kt @@ -0,0 +1,46 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.halilibo.richtext.ui.CodeBlock +import com.halilibo.richtext.ui.LocalInternalContentColor +import com.halilibo.richtext.ui.RichTextScope + +@Preview +@Composable +private fun CodeBlockPreviewOnWhite() { + CodeBlockPreview(backgroundColor = Color.White, contentColor = Color.Black) +} + +@Preview +@Composable +private fun CodeBlockPreviewOnBlack() { + CodeBlockPreview(backgroundColor = Color.Black, contentColor = Color.White) +} + +@Composable +private fun CodeBlockPreview( + backgroundColor: Color, + contentColor: Color +) { + CompositionLocalProvider(LocalInternalContentColor provides contentColor) { + Box(modifier = Modifier.background(color = backgroundColor)) { + Box(modifier = Modifier.padding(24.dp)) { + RichTextScope.CodeBlock( + """ + data class Hello( + val name: String + ) + """.trimIndent() + ) + } + } + } +} diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/FormattedListPreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/FormattedListPreview.kt new file mode 100644 index 00000000..98efc828 --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/FormattedListPreview.kt @@ -0,0 +1,79 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.LayoutDirection +import com.halilibo.richtext.ui.FormattedList +import com.halilibo.richtext.ui.ListType +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.Text + +@Preview +@Composable +private fun UnorderedListPreview() { + ListPreview(listType = ListType.Unordered, layoutDirection = LayoutDirection.Ltr) +} + +@Preview +@Composable +private fun UnorderedListPreviewRtl() { + ListPreview(listType = ListType.Unordered, layoutDirection = LayoutDirection.Rtl) +} + +@Preview +@Composable +private fun OrderedListPreview() { + ListPreview(listType = ListType.Ordered, layoutDirection = LayoutDirection.Ltr) +} + +@Preview +@Composable +private fun OrderedListPreviewRtl() { + ListPreview(listType = ListType.Ordered, layoutDirection = LayoutDirection.Rtl) +} + +@Composable +private fun ListPreview( + listType: ListType, + layoutDirection: LayoutDirection +) { + CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { + Box(Modifier.background(color = Color.White)) { + RichTextScope.FormattedList( + listType = listType, + items = listOf( + "Foo", + "Bar", + "Baz", + "Foo", + "Bar", + "Baz", + "Foo", + "Bar", + "Foo\nBar\nBaz", + "Foo" + ).withIndex() + .toList() + ) { (index, text) -> + Text(text) + if (index == 0) { + FormattedList(listType, @Composable { + Text("indented $text") + FormattedList(listType, @Composable { + Text("indented $text") + FormattedList(listType, @Composable { + Text("indented $text") + }) + }) + }) + } + } + } + } +} diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/HeadingPreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/HeadingPreview.kt new file mode 100644 index 00000000..56b26f5f --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/HeadingPreview.kt @@ -0,0 +1,41 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.halilibo.richtext.ui.Heading +import com.halilibo.richtext.ui.LocalInternalContentColor +import com.halilibo.richtext.ui.RichTextScope + +@Preview +@Composable +private fun HeadingPreviewOnWhite() { + HeadingPreview(backgroundColor = Color.White, contentColor = Color.Black) +} + +@Preview +@Composable +private fun HeadingPreviewOnBlack() { + HeadingPreview(backgroundColor = Color.Black, contentColor = Color.White) +} + +@Composable +private fun HeadingPreview( + backgroundColor: Color, + contentColor: Color +) { + CompositionLocalProvider(LocalInternalContentColor provides contentColor) { + Box(Modifier.background(color = backgroundColor)) { + Column { + for (level in 0 until 10) { + RichTextScope.Heading(level, "Heading ${level + 1}") + } + } + } + } +} diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TablePreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TablePreview.kt new file mode 100644 index 00000000..1ac580e9 --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TablePreview.kt @@ -0,0 +1,54 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.halilibo.richtext.ui.BlockQuote +import com.halilibo.richtext.ui.CodeBlock +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.Table +import com.halilibo.richtext.ui.Text + +@Preview +@Composable +private fun TablePreview() { + TablePreviewContents() +} + +@Preview +@Composable +private fun TablePreviewFixedWidth() { + TablePreviewContents() +} + +@Composable +private fun TablePreviewContents(modifier: Modifier = Modifier) { + RichTextScope.Table( + modifier = modifier + .background(Color.White) + .padding(4.dp), + headerRow = { + cell { Text("Column 1") } + cell { Text("Column 2") } + } + ) { + row { + cell { Text("Hello") } + cell { + CodeBlock("Foo bar") + } + } + row { + cell { + BlockQuote { + Text("Stuff") + } + } + cell { Text("Hello world this is a really long line that is going to wrap hopefully") } + } + } +} diff --git a/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TextPreview.kt b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TextPreview.kt new file mode 100644 index 00000000..7501d4c3 --- /dev/null +++ b/richtext-ui/src/jvmMain/kotlin/com/halilibo/richtext/ui/previews/TextPreview.kt @@ -0,0 +1,20 @@ +package com.halilibo.richtext.ui.previews + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.runtime.Composable +import com.halilibo.richtext.ui.RichTextScope +import com.halilibo.richtext.ui.string.RichTextString +import com.halilibo.richtext.ui.string.Text +import com.halilibo.richtext.ui.string.richTextString +import com.halilibo.richtext.ui.string.withFormat + +@Preview +@Composable +private fun TextPreview() { + RichTextScope.Text(richTextString { + append("I'm ") + withFormat(RichTextString.Format.Bold) { + append("bold!") + } + }) +} diff --git a/sample/build.gradle b/sample/build.gradle deleted file mode 100644 index 367decd7..00000000 --- a/sample/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -android rootProject.ext.defaultAndroidConfig - -dependencies { - implementation project(':printing') - implementation project(':richtext-commonmark') - implementation project(':richtext-ui') - implementation project(':richtext-ui-material') - implementation project(':slideshow') - implementation deps.androidx.appcompat - implementation deps.compose.activity - implementation deps.compose.foundation - implementation deps.compose.icons - implementation deps.compose.material - implementation deps.compose.tooling - - // For Layout Inspector. As of beta01 and Arctic Fox Canary 8, this causes the app to segfault. - // debugImplementation deps.kotlin.reflect -} diff --git a/sample/proguard-rules.pro b/sample/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/sample/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 9a79a437..00000000 --- a/settings.gradle +++ /dev/null @@ -1,14 +0,0 @@ -pluginManagement { - repositories { - gradlePluginPortal() - mavenCentral() - } -} - -include ':printing' -include ':richtext-ui' -include ':richtext-ui-material' -include ':richtext-commonmark' -include ':sample' -include ':slideshow' -rootProject.name = "compose-richtext" diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..bc50a89e --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + google() + gradlePluginPortal() + mavenCentral() + maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") } + } +} + +include(":printing") +include(":richtext-ui") +include(":richtext-ui-material") +include(":richtext-commonmark") +include(":android-sample") +include(":desktop-sample") +include(":slideshow") +rootProject.name = "compose-richtext" diff --git a/slideshow/build.gradle b/slideshow/build.gradle deleted file mode 100644 index 7ac8b42c..00000000 --- a/slideshow/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id('org.jetbrains.dokka') -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply from: rootProject.file('gradle/maven-publish.gradle') - -android rootProject.ext.defaultAndroidConfig - -dependencies { - implementation deps.compose.foundation - implementation deps.compose.material - implementation deps.compose.tooling - implementation deps.kotlin.stdlib -} diff --git a/slideshow/build.gradle.kts b/slideshow/build.gradle.kts new file mode 100644 index 00000000..3022eb7b --- /dev/null +++ b/slideshow/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + id("richtext-android-library") + id("org.jetbrains.dokka") +} + +dependencies { + implementation(Compose.foundation) + implementation(Compose.material) + implementation(Compose.tooling) +}