From 94a5237eaa652a544fc8b07fe3ebebe8a739f012 Mon Sep 17 00:00:00 2001 From: KotlinGeekDev Date: Mon, 26 Jan 2026 16:56:11 +0100 Subject: [PATCH] Foundations(iOS Sourceset): Provide implementation for fastFindURLs(). Make a test for it. --- .../nip10Notes/urls/UrlsDetectorTest.kt | 44 +++++++++++++++++++ .../vitorpamplona/quartz/utils/URLs.ios.kt | 8 +++- .../src/swift/swiftbridge/UrlDetector.swift | 21 +++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip10Notes/urls/UrlsDetectorTest.kt create mode 100644 quartz/src/swift/swiftbridge/UrlDetector.swift diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip10Notes/urls/UrlsDetectorTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip10Notes/urls/UrlsDetectorTest.kt new file mode 100644 index 000000000..b9e970077 --- /dev/null +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/nip10Notes/urls/UrlsDetectorTest.kt @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nip10Notes.urls + +import com.vitorpamplona.quartz.nip10Notes.content.findURLs +import com.vitorpamplona.quartz.utils.fastFindURLs +import kotlin.test.Test +import kotlin.test.assertContains +import kotlin.test.assertEquals + +class UrlsDetectorTest { + private val testSentence = "I have a website at https://mysite.xyz and a blog at https://myblog.xyz" + + @Test + fun detectUrlNumber() { + val detectedLinks = fastFindURLs(testSentence) + assertEquals(2, detectedLinks.size) + } + + @Test + fun urlsAreCorrect() { + val detectedLinks = findURLs(testSentence) + assertContains(detectedLinks, "https://mysite.xyz") + assertContains(detectedLinks, "https://myblog.xyz") + } +} diff --git a/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/utils/URLs.ios.kt b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/utils/URLs.ios.kt index 51e91a706..5dfc876ad 100644 --- a/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/utils/URLs.ios.kt +++ b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/utils/URLs.ios.kt @@ -20,6 +20,12 @@ */ package com.vitorpamplona.quartz.utils +import kotlinx.cinterop.ExperimentalForeignApi +import swiftbridge.UrlDetector + +@OptIn(ExperimentalForeignApi::class) actual fun fastFindURLs(text: String): List { - TODO("Not yet implemented") + val detectorInstance = UrlDetector() + return detectorInstance.findURLsWithText(text) as List +// TODO("Not yet implemented") } diff --git a/quartz/src/swift/swiftbridge/UrlDetector.swift b/quartz/src/swift/swiftbridge/UrlDetector.swift new file mode 100644 index 000000000..e4927c516 --- /dev/null +++ b/quartz/src/swift/swiftbridge/UrlDetector.swift @@ -0,0 +1,21 @@ +// +// Created by NullDev on 20/01/2026. +// + +import Foundation + +@objcMembers public class UrlDetector: NSObject { + public func findURLs(text: String) -> [String] { + var links = [String]() + let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) + let matches = detector.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count)) + + for match in matches { + guard let range = Range(match.range, in: text) else { continue } + let url = text[range] + links.append(String(url)) + } + + return links + } +} \ No newline at end of file