{"id":26266113,"url":"https://github.com/calvin-ll/autolinktext","last_synced_at":"2025-04-10T02:29:22.621Z","repository":{"id":226300970,"uuid":"767227374","full_name":"Calvin-LL/AutoLinkText","owner":"Calvin-LL","description":"A simple library that makes links, emails, and phone numbers clickable in text in Jetpack Compose and Kotlin Compose Multiplatform.","archived":false,"fork":false,"pushed_at":"2025-02-03T19:28:36.000Z","size":3754,"stargazers_count":72,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-03T00:08:14.903Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Calvin-LL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-04T23:15:52.000Z","updated_at":"2025-02-19T07:34:16.000Z","dependencies_parsed_at":"2025-02-03T20:32:22.968Z","dependency_job_id":null,"html_url":"https://github.com/Calvin-LL/AutoLinkText","commit_stats":null,"previous_names":["calvin-ll/autolinktext"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FAutoLinkText","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FAutoLinkText/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FAutoLinkText/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FAutoLinkText/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Calvin-LL","download_url":"https://codeload.github.com/Calvin-LL/AutoLinkText/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248144044,"owners_count":21054865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-14T03:16:52.371Z","updated_at":"2025-04-10T02:29:22.593Z","avatar_url":"https://github.com/Calvin-LL.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AutoLinkText\n\nAutoLinkText is a simple library that makes links, emails, and phone numbers clickable in text in Jetpack Compose and Kotlin Compose Multiplatform.\n\nThe latest demo app APK can be found in the [releases](https://github.com/Calvin-LL/AutoLinkText/releases) section under the \"Assets\" section of the latest release.\n\n## Motivation\n\n[`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.\n\n| Android                                                                                                                                                                                         | iOS                                                                                                                                                                                 |\n| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| \u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/android-dark.png\"\u003e\u003cimg alt=\"A screenshot of the demo app in Android\" src=\"assets/android-light.png\" width=\"320\"\u003e\u003c/picture\u003e | \u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/ios-dark.png\"\u003e\u003cimg alt=\"A screenshot of the demo app in iOS\" src=\"assets/ios-light.png\" width=\"320\"\u003e\u003c/picture\u003e |\n\n| Desktop                                                                                                                                                                                         | Web                                                                                                                                                                                 |\n| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| \u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/desktop-dark.png\"\u003e\u003cimg alt=\"A screenshot of the demo app in Desktop\" src=\"assets/desktop-light.png\" width=\"320\"\u003e\u003c/picture\u003e | \u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/web-dark.png\"\u003e\u003cimg alt=\"A screenshot of the demo app in Web\" src=\"assets/web-light.png\" width=\"320\"\u003e\u003c/picture\u003e |\n\n## Features\n\n- Make links, emails, and phone numbers clickable in your text out of the box\n- Create custom matchers for your own patterns (e.g. hashtags, mentions, etc.)\n- Customizable styling for links\n- Customizable click listeners for links\n- Supports Compose Multiplatform (Android, iOS, Desktop/JVM, Wasm, JS)\n\n## Usage\n\n### Version Catalog\n\nIf you're using Version Catalog, add the following to your `libs.versions.toml` file:\n\n```toml\n[versions]\n#...\nautolinktext = \"2.0.1\"\n\n[libraries]\n#...\nautolinktext = { module = \"sh.calvin.autolinktext:autolinktext\", version.ref = \"autolinktext\" }\n```\n\nor\n\n```toml\n[libraries]\n#...\nautolinktext = { module = \"sh.calvin.autolinktext:autolinktext\", version = \"2.0.1\" }\n```\n\n### Gradle\n\nIf you're using Gradle instead, add the following to your `build.gradle` file:\n\n#### Kotlin DSL\n\n```kotlin\ndependencies {\n    implementation(\"sh.calvin.autolinktext:autolinktext:2.0.1\")\n}\n```\n\n#### Groovy DSL\n\n```groovy\ndependencies {\n    implementation 'sh.calvin.autolinktext:autolinktext:2.0.1'\n}\n```\n\n### Examples\n\nSee [demo app code](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/autolinktext/demo/App.kt) for more examples.\n\n#### Basic Usage\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/basic-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/basic-light.png\"\u003e\u003c/picture\u003e\n\nBy default `AutoLinkText` turns URLs, emails, and phone numbers into clickable links, set the color to `MaterialTheme.colorScheme.primary`, and underline the links.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"\"\"\n        |Visit https://www.google.com\n        |Visit www.google.com\n        |Email test@example.com\n        |Call 6045557890\n        |Call +1 (604) 555-7890\n        |Call 604-555-7890\n        \"\"\".trimMargin()\n    )\n)\n```\n\n#### Customize Link Color\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/custom-color-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/custom-color-light.png\"\u003e\u003c/picture\u003e\n\nYou can override the default styling by providing a `TextLinkStyles` object.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"...\",\n        defaultLinkStyles = TextLinkStyles(\n            SpanStyle(\n                color = Color.Blue,\n                textDecoration = TextDecoration.Underline\n            )\n        )\n    )\n)\n```\n\n#### Make Your Own Rules\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/make-rule-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/make-rule-light.png\"\u003e\u003c/picture\u003e\n\nThere are 3 types of `TextRule`s: `Url`, `Clickable`, and `Styleable`.\n\n- `Url` turns matched text into a clickable link, and when clicked, opens the URL.\n- `Clickable` turns matched text into a clickable link, and when clicked, calls the `onClick` lambda.\n- `Styleable` applies a `SpanStyle` to the matched text.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"Make your own rules like #hashtag and @mention\",\n        textRules = listOf(\n            TextRule.Styleable(\n                textMatcher = TextMatcher.StringMatcher(\"Make\"),\n                style = SpanStyle(fontWeight = FontWeight.Bold)\n            ),\n            TextRule.Clickable(\n                textMatcher = TextMatcher.RegexMatcher(Regex(\"#\\\\w+\")),\n                onClick = {\n                    println(\"Hashtag ${it.matchedText} clicked\")\n                },\n            ),\n            TextRule.Url(\n                textMatcher = TextMatcher.RegexMatcher(Regex(\"@\\\\w+\")),\n                styles = TextLinkStyles(\n                    SpanStyle(\n                        color = Color.Blue\n                    )\n                ),\n                urlProvider = { \"https://twitter.com/${it.matchedText}\" }\n            )\n        )\n    )\n)\n```\n\n#### Different Styles for Different Matches\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/different-style-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/different-style-light.png\"\u003e\u003c/picture\u003e\n\nProvide a `stylesProvider` lambda that returns a `TextLinkStyles` object based on the matched text.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"Style the same rule differently like #hashtag1 and #hashtag2\",\n        textRules = listOf(\n            TextRule.Clickable(\n                textMatcher = TextMatcher.RegexMatcher(Regex(\"#\\\\w+\")),\n                stylesProvider = {\n                    val hashtag = it.matchedText\n                    if (hashtag == \"#hashtag1\") {\n                        TextLinkStyles(\n                            SpanStyle(\n                                color = Color.Red,\n                                textDecoration = TextDecoration.Underline\n                            )\n                        )\n                    } else {\n                        TextLinkStyles(\n                            SpanStyle(\n                                color = Color.Blue,\n                                textDecoration = TextDecoration.Underline\n                            )\n                        )\n                    }\n                },\n                onClick = {\n                    println(\"Hashtag ${it.matchedText} clicked\")\n                },\n            ),\n        )\n    )\n)\n```\n\n#### `TextRule`s don't have to be clickable\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/not-clickable-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/not-clickable-light.png\"\u003e\u003c/picture\u003e\n\nYou can create `TextRule`s that are not clickable by using `TextRule.Styleable`.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"This is very important\",\n        textRules = listOf(\n            TextRule.Styleable(\n                textMatcher = TextMatcher.StringMatcher(\"important\"),\n                style = SpanStyle(color = Color.Red),\n            )\n        ),\n    )\n)\n```\n\n#### Make Your Own Matcher\n\n\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/make-matcher-dark.png\"\u003e\u003cimg alt=\"\" src=\"assets/make-matcher-light.png\"\u003e\u003c/picture\u003e\n\nCreate your own matchers with `TextMatcher.FunctionMatcher` that takes the given text and returns a list of `SimpleTextMatchResult`s.\n\n```kotlin\nText(\n    AnnotatedString.rememberAutoLinkText(\n        \"Make every  other  word blue\",\n        textRules = listOf(\n            TextRule.Styleable(\n                textMatcher = TextMatcher.FunctionMatcher {\n                    val matches = mutableListOf\u003cSimpleTextMatchResult\u003cNothing?\u003e\u003e()\n                    var currentWordStart = 0\n                    \"$it \".forEachIndexed { index, char -\u003e\n                        if (char.isWhitespace()) {\n                            val match = SimpleTextMatchResult(\n                                start = currentWordStart,\n                                end = index,\n                            )\n                            if (it.slice(match).isNotBlank()) {\n                                matches.add(match)\n                            }\n                            currentWordStart = index + 1\n                        }\n                    }\n                    matches.filterIndexed { index, _ -\u003e index % 2 == 0 }\n                },\n                style = SpanStyle(color = Color.Blue),\n            ),\n        ),\n    )\n)\n```\n\n## API\n\n- [AutoLinkText](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/AutoLinkText.kt)\n- [TextRule](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [Url](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [Clickable](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [Styleable](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n- [TextRuleDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n  - [defaultList](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextRule.kt)\n- [TextMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [RegexMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [StringMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [FunctionMatcher](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n- [TextMatcherDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n  - [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatcher.kt)\n- [MatchFilter](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)\n- [MatchFilterDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)\n  - [NoOp](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)\n  - [WebUrls](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)\n  - [PhoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchFilter.kt)\n- [MatchStylesProvider](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchStylesProvider.kt)\n- [SimpleTextMatchResult](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/SimpleTextMatchResult.kt)\n- [TextMatchResult](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/TextMatchResult.kt)\n- [MatchClickHandlerDefaults](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)\n  - [webUrl](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)\n  - [emailAddress](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)\n  - [phoneNumber](autolinktext/src/commonMain/kotlin/sh/calvin/autolinktext/MatchClickHandler.kt)\n\n## Running the demo app\n\nTo run the Android demo app, open the project in Android Studio and run the app.\n\nTo 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.\n\n![Android Studio Debug Configuration Page](assets/android-studio-config.png)\n\nTo run the web demo app, run `./gradlew :composeApp:wasmJsBrowserDevelopmentRun`.\n\nTo run the desktop demo app, run `./gradlew :demoApp:ComposeApp:run`.\n\n## Contributing\n\nOpen this project with Android Studio Preview.\n\nYou'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.\n\n## License\n\n```\nCopyright 2023 Calvin Liang\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalvin-ll%2Fautolinktext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcalvin-ll%2Fautolinktext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalvin-ll%2Fautolinktext/lists"}