Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Calvin-LL/AutoLinkText
A simple library that makes links, emails, and phone numbers clickable in text in Jetpack Compose and Kotlin Compose Multiplatform.
https://github.com/Calvin-LL/AutoLinkText
Last synced: 4 months ago
JSON representation
A simple library that makes links, emails, and phone numbers clickable in text in Jetpack Compose and Kotlin Compose Multiplatform.
- Host: GitHub
- URL: https://github.com/Calvin-LL/AutoLinkText
- Owner: Calvin-LL
- License: apache-2.0
- Created: 2024-03-04T23:15:52.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-03-10T08:33:37.000Z (10 months ago)
- Last Synced: 2024-03-10T09:30:48.284Z (10 months ago)
- Language: Kotlin
- Homepage:
- Size: 2.19 MB
- Stars: 18
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- jetpack-compose-awesome - AutoLinkText - Make links, emails, and phone numbers clickable in text (Libraries / Testings)
- jetpack-compose-awesome - AutoLinkText - Make links, emails, and phone numbers clickable in text (Libraries / Testings)
README
# AutoLinkText
AutoLinkText is a simple library that makes links, emails, and phone numbers clickable in text in Jetpack Compose and Kotlin Compose Multiplatform.
## Motivation
[`TextView`](https://developer.android.com/reference/android/widget/TextView) has [`autoLink`](https://developer.android.com/reference/android/widget/TextView#attr_android:autoLink) and [`Linkify`](https://developer.android.com/reference/android/text/util/Linkify) but Compose doesn't have an equivalent. This library aims to fill that gap.
| Android | iOS |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| | || Desktop | Web |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| | |## Features
- Make links, emails, and phone numbers clickable in your text out of the box
- Create custom matchers for your own patterns (e.g. hashtags, mentions, etc.)
- Customizable styling for links
- Customizable click listeners for links
- Supports Compose Multiplatform (Android, iOS, Desktop/JVM, Wasm)## Usage
### Version Catalog
If you're using Version Catalog, add the following to your `libs.versions.toml` file:
```toml
[versions]
#...
autolinktext = "1.1.1"[libraries]
#...
autolinktext = { module = "sh.calvin.autolinktext:autolinktext", version.ref = "autolinktext" }
```or
```toml
[libraries]
#...
autolinktext = { module = "sh.calvin.autolinktext:autolinktext", version = "1.1.1" }
```### Gradle
If you're using Gradle instead, add the following to your `build.gradle` file:
#### Kotlin DSL
```kotlin
dependencies {
implementation("sh.calvin.autolinktext:autolinktext:1.1.1")
}
```#### Groovy DSL
```groovy
dependencies {
implementation 'sh.calvin.autolinktext:autolinktext:1.1.1'
}
```### Examples
See [demo app code](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/autolinktext/demo/App.kt) for more examples.
#### Basic Usage
By default `AutoLinkText` turns URLs, emails, and phone numbers into clickable links and underlines them.
```kotlin
AutoLinkText(
text = """
|Visit https://www.google.com
|Visit www.google.com
|Email [email protected]
|Call 6045557890
|Call +1 (604) 555-7890
|Call 604-555-7890
""".trimMargin(),
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
)
```#### Customize Link Color
You can override the default styling by mapping over the default list of rules and changing the `style` in each default rule.
```kotlin
AutoLinkText(
text = "...",
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
textRules = TextRuleDefaults.defaultList().map {
it.copy(
style = SpanStyle(
color = MaterialTheme.colorScheme.primary,
textDecoration = TextDecoration.Underline
)
)
}
)
```#### Make Your Own Rules
Create your own rules by providing `TextRule`s with a `TextMatcher`, an optional `MatchStyle` for the matched text and an optional `onClick` lambda.
```kotlin
AutoLinkText(
text = "Make your own rules like #hashtag and @mention",
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
textRules = listOf(
TextRule(
textMatcher = TextMatcher.RegexMatcher(Regex("#\\w+")),
style = SpanStyle(
color = MaterialTheme.colorScheme.primary,
textDecoration = TextDecoration.Underline
),
onClick = {
println("Hashtag ${it.matchedText} clicked")
},
annotationProvider = { "https://link.to.hashtag" },
),
TextRule(
textMatcher = TextMatcher.RegexMatcher(Regex("@\\w+")),
style = SpanStyle(
color = MaterialTheme.colorScheme.secondary,
textDecoration = TextDecoration.Underline
),
onClick = {
println("Mention ${it.matchedText} clicked")
},
annotationProvider = { "https://link.to.mentions" },
)
)
)
```#### Match Dependent Styling
Use `styleProvider` to provide a `SpanStyle` based on the matched text.
```kotlin
AutoLinkText(
text = "Style the same rule differently like #hashtag1 and #hashtag2",
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
textRules = listOf(
TextRule(
textMatcher = TextMatcher.RegexMatcher(Regex("#\\w+")),
styleProvider = {
val hashtag = it.matchedText
if (hashtag == "#hashtag1") {
SpanStyle(
color = Color.Red,
textDecoration = TextDecoration.Underline
)
} else {
SpanStyle(
color = Color.Blue,
textDecoration = TextDecoration.Underline
)
}
},
onClick = {
println("Hashtag ${it.matchedText} clicked")
},
annotationProvider = { "https://link.to.hashtag" },
),
)
)
```#### `TextRule`s don't have to be Clickable
You can create `TextRule`s that are not clickable by not providing an `onClick` lambda.
```kotlin
AutoLinkText(
text = "This is very important",
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
textRules = listOf(
TextRule(
textMatcher = TextMatcher.StringMatcher("important"),
style = SpanStyle(color = Color.Red),
annotationProvider = { null },
),
)
)
```#### Make Your Own Matcher
Create your own matchers with `TextMatcher.FunctionMatcher` that takes the given text and returns a list of `SimpleTextMatchResult`s.
```kotlin
AutoLinkText(
text = "Make every other word blue",
style = LocalTextStyle.current.copy(
color = LocalContentColor.current,
),
textRules = listOf(
TextRule(
textMatcher = TextMatcher.FunctionMatcher {
val matches = mutableListOf>()
var currentWordStart = 0
"$it ".forEachIndexed { index, char ->
if (char.isWhitespace()) {
val match = SimpleTextMatchResult(
start = currentWordStart,
end = index,
)
if (it.slice(match).isNotBlank()) {
matches.add(match)
}
currentWordStart = index + 1
}
}
matches.filterIndexed { index, _ -> index % 2 == 0 }
},
style = SpanStyle(color = Color.Blue),
annotationProvider = { null },
),
)
)
```## Caveats
- Google seems to be working on replacing [`ClickableText`]() API with [`LinkAnnotation`](https://developer.android.com/reference/kotlin/androidx/compose/ui/text/LinkAnnotation) but it is not functional yet. I will try my best to keep this library up to date with the latest Compose APIs.
- The default list of `TextRule`s are accessible. But at the moment accessibility is not great if you add `TextRule`s with onClick function that does something other than opening a link because of a bug with [`ClickableText`](). Hopefully this gets fixed in the future (See [Google IssueTracker issue 274486643](https://issuetracker.google.com/issues/274486643)).## API
- [AutoLinkText](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/AutoLinkText.kt)
- [TextRule](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [TextRuleDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [defaultList](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)
- [TextMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [RegexMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [StringMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [FunctionMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [TextMatcherDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)
- [MatchFilter](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)
- [MatchFilterDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)
- [NoOp](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)
- [WebUrls](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)
- [PhoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)
- [MatchStyleProvider](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchStyleProvider.kt)
- [SimpleTextMatchResult](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/SimpleTextMatchResult.kt)
- [TextMatchResult](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatchResult.kt)
- [MatchClickHandlerDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)
- [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)
- [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)
- [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)## Running the demo app
To run the Android demo app, open the project in Android Studio and run the app.
To run the iOS demo app, open the iosApp project in Xcode and run the app or add the following Configuration to the Android Studio project, you may need to install the [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) first.
![Android Studio Debug Configuration Page](assets/android-studio-config.png)
To run the web demo app, run `./gradlew :composeApp:wasmJsBrowserDevelopmentRun`.
To run the desktop demo app, run `./gradlew :demoApp:ComposeApp:run`.
## Contributing
Open this project with Android Studio Preview.
You'll want to install the [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) in Android Studio before you open this project.
## License
```
Copyright 2023 Calvin LiangLicensed 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 athttp://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.
```